home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / nn.zip / PATCH07 < prev    next >
Text File  |  1989-12-31  |  199KB  |  7,371 lines

  1. *** /usr/storm/nn6.3.0/INSTALLATION    Thu Jun  1 11:10:40 1989
  2. --- INSTALLATION    Fri Sep  8 12:46:39 1989
  3. ***************
  4. *** 46,71 ****
  5. --- 46,89 ----
  6.   Among the things you have to select are two system and machine
  7.   dependent files.  The following system files are delivered with nn:
  8.   
  9. +     s-3b1g.h    For 3b1 (unix-pc) with GCC.
  10. +     s-aux1-1.h    For A/UX 1.1
  11.       s-bsd4-2.h    For 4.2 BSD and Ultrix systems
  12.       s-bsd4-3.h    For 4.3 BSD systems
  13. +     s-dnix5-2.h    For dnix on DIAB DS90-10.
  14. +     s-dynix3-0.h    For Dynix 3.0 on Symmetry.
  15. +     s-fortune.h    For Fortune 32:16 [read comments in the file]
  16.       s-hpux.h    For HPUX (series 320)
  17.       s-hpux2-1.h    For HPUX 2.1 (series 800)
  18. +     s-hpux3-0.h    For HPUX 3.0 (series 800)
  19. +     s-pyramid.h    For Pyramid (and Targon 35).
  20. +     s-sgi4D.h    For IRIX 3.1/3.2 [read comments in the file]
  21.       s-sunos3.h    For SunOS 3
  22.       s-sunos4-0.h    For SunOS 4.0
  23.       s-tower32.h    For NCR tower
  24. +     s-uport2-2.h    For Microport UNIX V.2
  25.       s-usg3-1.h    For most system V systems (also 2.2)
  26. +     s-xenix386.h    For xenix386 [termcap version].
  27. +     s-xenix386ds.h    For Xenix386 2.3.2 w/dev system [try it out!].
  28.   
  29.   The following machine description files are delivered with nn:
  30.   
  31. +     m-3b1g.h    For 3b1 (unix-pc) with GCC [no networking].
  32.       m-att3b.h    For AT&T 3b2 (with s-usg3-1.h)
  33. +     m-convex.h    For Convex.
  34.       m-dec3100.h    For DECstation 3100 (with s-bsd4-2.h)
  35.       m-gould.h    For Gould PN6000 (with s-bsd4-3.h)
  36.       m-hp9000.h    For HP9000 series 320 and 800 (at least)
  37. +     m-i80286.h    For Intel 80286 processors [no network support]
  38.       m-m680x0.h    For 68000 family processors
  39. +     m-pyramid.h    For Pyramid (and Targon 35).
  40. +     m-sgi4D.h    For Silicon Graphics 4D series.
  41.       m-sparc.h    For SPARC processors
  42.       m-sun.h        For 680x0 based SUNs
  43.       m-sun386i.h    For 80386 based SUNs
  44. +     m-symmetry.h    For Sequent Symmetry.
  45.       m-vax.h        For VAX family
  46. +     m-xenix386.h    For XENIX 386 [no network support]
  47.   
  48.   If you cannot use one of these configuration files, create your own 
  49.   based on the following template files (send the new system and/or
  50. ***************
  51. *** 321,326 ****
  52. --- 339,345 ----
  53.       $ make all
  54.       $ su
  55.       # make install
  56. +     # make online
  57.   
  58.   To be able to install a new nnmaster, the currently running master (if
  59.   any) will be stopped automatically, and it has to be started manually
  60. *** /usr/storm/nn6.3.4/MANIFEST    Mon Jul 10 13:36:15 1989
  61. --- MANIFEST    Fri Sep  8 12:46:39 1989
  62. ***************
  63. *** 46,51 ****
  64. --- 46,52 ----
  65.   keymap.h
  66.   kill.c
  67.   log_entry.c
  68. + m-3b1g.h
  69.   m-att3b.h
  70.   m-convex.h
  71.   m-dec3100.h
  72. ***************
  73. *** 53,58 ****
  74. --- 54,60 ----
  75.   m-hp9000.h
  76.   m-i80286.h
  77.   m-m680x0.h
  78. + m-pyramid.h
  79.   m-sgi4D.h
  80.   m-sparc.h
  81.   m-sun.h
  82. ***************
  83. *** 100,105 ****
  84. --- 102,108 ----
  85.   regexp.h
  86.   reroute.c
  87.   routes.sample
  88. + s-3b1g.h
  89.   s-aux1-1.h
  90.   s-bsd4-2.h
  91.   s-bsd4-3.h
  92. ***************
  93. *** 109,114 ****
  94. --- 112,118 ----
  95.   s-hpux.h
  96.   s-hpux2-1.h
  97.   s-hpux3-0.h
  98. + s-pyramid.h
  99.   s-sgi4D.h
  100.   s-sunos3.h
  101.   s-sunos4-0.h
  102. ***************
  103. *** 117,122 ****
  104. --- 121,127 ----
  105.   s-uport2-2.h
  106.   s-usg3-1.h
  107.   s-xenix386.h
  108. + s-xenix386ds.h
  109.   save.c
  110.   selection.c
  111.   sequence.c
  112. *** /usr/storm/nn6.3.0/NNTP    Thu Jun  1 11:10:40 1989
  113. --- NNTP    Fri Sep  8 12:46:40 1989
  114. ***************
  115. *** 1,17 ****
  116.   NNTP SUPPORT
  117.   ------------
  118.   
  119. ! This file describes the NNTP support available in nn release 6.3.
  120. ! The NNTP support was implemented by Rene Seindal, seindal@diku.dk
  121.   
  122.   
  123.   PREREQUISITES
  124.   -------------
  125.   
  126. ! Before you can use the NNTP part of nn, you need to get and install
  127. ! the nntp-1.5 distribution with patches 1-3.  It is available from
  128. ! several ftp-sites in the USA.  It is also available on freja.diku.dk
  129. ! (ip 129.142.96.1) together with the nn 6.3 distribution.
  130.   
  131.   You also need read-access to an NNTP-server.
  132.   
  133. --- 1,17 ----
  134.   NNTP SUPPORT
  135.   ------------
  136.   
  137. ! This file describes the NNTP support available in nn release 6.3.  The
  138. ! NNTP support was implemented by Rene' Seindal, seindal@diku.dk
  139.   
  140.   
  141.   PREREQUISITES
  142.   -------------
  143.   
  144. ! Before you can use the NNTP part of nn, you need to get and install the
  145. ! nntp-1.5 distribution with patches 1-3.  It is available from several
  146. ! ftp-sites in the USA.  It is also available on freja.diku.dk (ip
  147. ! 129.142.96.1) together with the nn 6.3 distribution.
  148.   
  149.   You also need read-access to an NNTP-server.
  150.   
  151. ***************
  152. *** 26,45 ****
  153.   
  154.   When the master is set up to use NNTP, it will connect to the NNTP-
  155.   server in each iteration of the collection (the interval set with -r),
  156. ! get a copy of the active file, and incorporate the new articles into
  157. ! the database.  To do this, the master will temporarily transfer one
  158. ! article at a time from the NNTP-server to the local system.
  159.   
  160.   When the articles are read with nn, it will use the local database to
  161.   present the menus, and fetch the articles from the NNTP-server as they
  162. ! are requested by the user.  It will connect to the NNTP server the
  163. ! first time it is necessary to fetch an article.
  164.   
  165.   Neither nnmaster, nor nn will use NNTP if they run on the NNTP-server
  166.   itself (they will directly access the news files).
  167.   
  168. ! Both nn and nnmaster access the server in reading mode.  The master
  169. ! and all client MUST use the same server at all times, since the local
  170.   database contains article numbers, that are only unique for each
  171.   NNTP-server.
  172.   
  173. --- 26,45 ----
  174.   
  175.   When the master is set up to use NNTP, it will connect to the NNTP-
  176.   server in each iteration of the collection (the interval set with -r),
  177. ! get a copy of the active file, and incorporate the new articles into the
  178. ! database.  To do this, the master will temporarily transfer one article
  179. ! at a time from the NNTP-server to the local system.
  180.   
  181.   When the articles are read with nn, it will use the local database to
  182.   present the menus, and fetch the articles from the NNTP-server as they
  183. ! are requested by the user.  It will connect to the NNTP server the first
  184. ! time it is necessary to fetch an article.
  185.   
  186.   Neither nnmaster, nor nn will use NNTP if they run on the NNTP-server
  187.   itself (they will directly access the news files).
  188.   
  189. ! Both nn and nnmaster access the server in reading mode.  The master and
  190. ! all client MUST use the same server at all times, since the local
  191.   database contains article numbers, that are only unique for each
  192.   NNTP-server.
  193.   
  194. ***************
  195. *** 47,64 ****
  196.   SHARING THE DATABASE
  197.   --------------------
  198.   
  199. ! You must also decide whether you want to share the database between
  200. ! your local news clients, and how you are going to do it.
  201.   
  202. ! The database will take up some disk space, normally about 1Mb per
  203. ! 10.000 articles.  There are several ways to manage this space.
  204. ! This simplest solution, is to let each client run it own master,
  205. ! i.e., have its own database.  This means, of course, no sharing.
  206.   
  207. ! Alternatively, one host can run the master, and distribute the
  208. ! database to the others via e.g., rdist.  This doesn't save disk space,
  209. ! but saves load on the NNTP-server.
  210.   
  211.   Last, the database can be shared with NFS/RFS (see the description of
  212.   NETWORK_DATABASE in the config.h file).
  213. --- 47,64 ----
  214.   SHARING THE DATABASE
  215.   --------------------
  216.   
  217. ! You must also decide whether you want to share the database between your
  218. ! local news clients, and how you are going to do it.
  219.   
  220. ! The database will take up some disk space, normally about 1Mb per 10.000
  221. ! articles.  There are several ways to manage this space.
  222. ! This simplest solution, is to let each client run it own master, i.e.,
  223. ! have its own database.  This means, of course, no sharing.
  224.   
  225. ! Alternatively, one host can run the master, and distribute the database
  226. ! to the others via e.g., rdist.  This doesn't save disk space, but saves
  227. ! load on the NNTP-server.
  228.   
  229.   Last, the database can be shared with NFS/RFS (see the description of
  230.   NETWORK_DATABASE in the config.h file).
  231. ***************
  232. *** 77,110 ****
  233.   NNTP
  234.       You enable the use of NNTP by defining the macro NNTP.
  235.   
  236. ! NNTP_SERVER 
  237.       Both the master and the clients will look up their NNTP-server
  238. !     in the file given by the macro NNTP_SERVER.  If the name is
  239. !     not an absolute path name, it is taken to be relative to
  240.       LIB_DIRECTORY.
  241. !     
  242.       The format of the file is compatible with the one used in
  243.       clientlib.c in the nntp-1.5 distribution, i.e., the first
  244. !     non-blank line, not starting with '#' is taken to be the name
  245. !     of the NNTP-server.  This file MUST be present, and must
  246. !     contain a valid host name.
  247.   
  248.   
  249. ! Tuning
  250. ! ------
  251.   
  252.   Both the server and each client maintains a cache of recently accessed
  253.   articles, to minimize communication with the server (mainly to avoid
  254.   fetching large digests continuously).  The master needs the cache when
  255. ! it splits digests, and the clients need it, because nn has a tendency
  256. ! to reopen the articles several times.
  257.   
  258. ! The master's cache is kept in LIB_DIRECTORY, and each client's cache
  259. ! are kept in the users .nn directory.  The constant NNTPCACHE (defined
  260. ! in nntp.c but can be redefined in config.h) defines the size of the
  261. ! cache, whose optimal size depends on the amount of news kept on line
  262. ! on the NNTP-server.  Values of 5-10 gives reasonable results.  The
  263. ! effect is most striking when reading digested news.
  264.   
  265.   
  266.   INSTALLATION
  267. --- 77,122 ----
  268.   NNTP
  269.       You enable the use of NNTP by defining the macro NNTP.
  270.   
  271. ! NNTP_SERVER
  272.       Both the master and the clients will look up their NNTP-server
  273. !     in the file given by the macro NNTP_SERVER.  If the name is not
  274. !     an absolute path name, it is taken to be relative to
  275.       LIB_DIRECTORY.
  276.       The format of the file is compatible with the one used in
  277.       clientlib.c in the nntp-1.5 distribution, i.e., the first
  278. !     non-blank line, not starting with '#' is taken to be the name of
  279. !     the NNTP-server.  This file MUST be present, and must contain a
  280. !     valid host name.
  281. ! NNTP_POST
  282. !     If you use the NNTP based inews (part on the NNTP distribution)
  283. !     and you have hosts that are not allowed to post to the NNTP
  284. !     server, you should defined this.  It will make nn check at
  285. !     connect time whether the NNTP server allows postings, and reject
  286. !     all attempts to post, if the server disallows posting.  If you
  287. !     do not define this, users will be allowed to post by nn, but the
  288. !     posting will eventually fail.
  289. !     Again, this parameter is only relevant, if you use the NNTP
  290. !     based inews, and have hosts that are not allowed to post.
  291.   
  292.   
  293. ! TUNING
  294. !  ------
  295.   
  296.   Both the server and each client maintains a cache of recently accessed
  297.   articles, to minimize communication with the server (mainly to avoid
  298.   fetching large digests continuously).  The master needs the cache when
  299. ! it splits digests, and the clients need it, because nn has a tendency to
  300. ! reopen the articles several times.
  301.   
  302. ! The master's cache is kept in LIB_DIRECTORY, and each client's cache are
  303. ! kept in the users .nn directory.  The constant NNTPCACHE (defined in
  304. ! nntp.c but can be redefined in config.h) defines the size of the cache,
  305. ! whose optimal size depends on the amount of news kept on line on the
  306. ! NNTP-server.  Values of 5-10 gives reasonable results.  The effect is
  307. ! most striking when reading digested news.
  308.   
  309.   
  310.   INSTALLATION
  311. ***************
  312. *** 117,157 ****
  313.   Notice however, that the NNTP_SERVER file must be properly initialized
  314.   before doing the 'make initdb'.
  315.   
  316. ! If something goes wrong in the initialization of the database, you
  317. ! will have to run 'nnmaster -I' again by hand.
  318.   
  319.   
  320.   PROBLEMS
  321.   --------
  322.   
  323. ! There are some problems with the current implementation, mostly in
  324. ! connection with error conditions.  Almost any error will cause a
  325. ! panic-like reaction.  The master simply closes the connection and
  326. ! returns to the main loop, and nn terminates the session.
  327.   
  328. ! The client program, nn, has a simple attitude towards such accidents.
  329. ! It prints a message, clears the cache, and exits.  This means that you
  330. ! can't have an nn suspended for very long before the connection times
  331. ! out, and nn will exit the next time you try to access an article.
  332. ! This is clearly wrong.  It should at least just close the connection,
  333. ! and reopen it the next time a request to the server comes in.
  334. ! In spite of these drawbacks, in general it works ok.  The NNTP code
  335. ! has been in use for several months now, in a generally satisfying
  336. ! manner.
  337. ! Alternative implementations can be conceived, especially in the
  338. ! master.  The master normally collects articles by rereading the active
  339. ! file, looking for changed article numbers.  For each group with new
  340. ! articles, it reads the new articles and adds them to the database.
  341. ! This scheme has been kept in the NNTP-based master, to keep the
  342. ! changes at a minimum.
  343.   
  344.   An alternative solution could be to use NEWNEWS to get a list of new
  345. ! articles since last collect, and fetch each article in sequence.  This
  346. ! requires the NNTP-server to return the article number in the response
  347. ! to an ARTICLE request (as required in rfc 977), but apparently version
  348. ! 1.5 of the NNTP-server does not do this.
  349.   
  350. ! Suggestions and improvements are very much welcome.  Send your
  351.   contributions to nn-bugs@dkuug.dk.
  352. --- 129,207 ----
  353.   Notice however, that the NNTP_SERVER file must be properly initialized
  354.   before doing the 'make initdb'.
  355.   
  356. ! If something goes wrong in the initialization of the database, you will
  357. ! have to run 'nnmaster -I' again by hand.
  358. ! ERROR HANDLING
  359. ! --------------
  360. ! The handling of errors have been improved since the initial release.
  361. ! The master will handle most errors by closing the connection, and
  362. ! returning to the main loop.  All errors in the master are logged, with a
  363. ! code of `N,' so they can be inspected with the (undocumented?) `n'
  364. ! command in nnadmin's Log menu.
  365. ! A few errors are considere fatal. If any of these occur operation will
  366. ! be discontinued.  These errors are such as failure to find the NNTP
  367. ! server, failure to find the NNTP service, and responses from the NNTP
  368. ! server in the 500 range (ill-formed requests, access denied, ...)
  369. ! NNTP server timeouts are handled specially.  If the NNTP server times
  370. ! out, both nn and the master will attempt to restart it (by connecting
  371. ! again).  This shouldn't happen in the master (which won't leave sockets
  372. ! idle for that long), but it can easily happen in nn, if it is left
  373. ! suspended for too long.  If the server responds with code 400 (Service
  374. ! discontinued), a reconnect is also tried.
  375.   
  376.   
  377.   PROBLEMS
  378.   --------
  379.   
  380. ! I am not certain what should happen if the server sends back responses
  381. ! in the 1xx range.  I do not know whether a NNTP server is allowed to
  382. ! return one of these responses on its own initiative.  If it is, nn
  383. ! should probably ignore (or display) the messages.  Currently, nothing is
  384. ! done to treat these responses in any way.
  385. ! I have seen a strange thing happen to the master, which I have not been
  386. ! able to reproduce.  The master ran on a Sun-4 running SunOS 4.0, and the
  387. ! NNTP server was a VAX 785 running MORE/bsd.  The NNTP software was
  388. ! version 1.5.3.  The master was stuck in a read from the NNTP server.  A
  389. ! netstat on the Sun show an established connection to nntpd on the Vax,
  390. ! but a netstat on the Vasx did not show any NNTP connections.  There was
  391. ! no nntpd running, and no messages on the console indicating any
  392. ! failures.
  393. ! If you see this happen, please compile nntp.c with the macro DEBUG
  394. ! defined, and relink the master.  The master will then leave a transcript
  395. ! of the conversation between the master and the NNTP server in
  396. ! /usr/tmp/nnmaster.log.  If the master gets stuck again, save this file
  397. ! before you restart the master, and send it to me.  The file is truncated
  398. ! each time the master connects to the NNTP server, so it won't fill up
  399. ! your disk.  If you compile nn with nntp debug enabled, it will be a very
  400. ! annoying program, so you probably don't want to do that.
  401. ! ALTERNATIVES
  402. ! ------------
  403.   
  404. ! Alternative implementations can be conceived, especially in the master.
  405. ! The master normally collects articles by rereading the active file,
  406. ! looking for changed article numbers.  For each group with new articles,
  407. ! it reads the new articles and adds them to the database.  This scheme
  408. ! has been kept in the NNTP-based master, to keep the changes at a
  409. ! minimum.
  410.   
  411.   An alternative solution could be to use NEWNEWS to get a list of new
  412. ! articles since last collect, and fetch each article in sequence.  The
  413. ! newsgroups and article numbers within each group could then be found in
  414. ! the Xref: field.  This would probably improve efficiency, since the
  415. ! master would then generate fewer failing requests (for non-existent
  416. ! articles), and it would only read cross-posted articles once.  This
  417. ! solution would, however, require some surgery on the current structure
  418. ! of the masters main loop.
  419.   
  420. ! Suggestions and improvements are very much welcome.  Send your ideas or
  421.   contributions to nn-bugs@dkuug.dk.
  422. *** /usr/storm/nn6.3.0/PROBLEMS    Thu Jun  1 11:10:40 1989
  423. --- PROBLEMS    Fri Sep  8 12:46:40 1989
  424. ***************
  425. *** 2,7 ****
  426. --- 2,24 ----
  427.   installation and operation of nn in the past.
  428.   
  429.   
  430. + RUNNING NN ON 80286
  431. + -------------------
  432. + The system and machine file for a '286 running Microport UNIX V/AT are
  433. + s-uport2-2.h and m-i80286.h, but to get it running you probably have
  434. + to do the following things as well:
  435. + - tgetstr.o in libcurses is broken in 2.4.
  436. +   Get an old version (e.g. 1.3) and replaced tgetstr.o.
  437. + - Use the m286 malloc posted recently to comp.sources.misc
  438. + Thanks to Wietse Z. Venema and Miek Grenier for a lot of work on 
  439. + locating and fixing 16/32 bit problems in nn which caused it not to
  440. + work on the '286.
  441.   FILE PERMISSIONS
  442.   ----------------
  443.   
  444. ***************
  445. *** 94,103 ****
  446.      clearing the message, and should offer the possibility to
  447.      re-try the operation (which usually then works for us).
  448.   
  449.   
  450.   
  451. ! ECHOING TYPED CHARACTERS
  452. ! ------------------------
  453.   
  454.   nn does not echo the characters you type except when you are entering
  455.   a string, e.g. a file name.  Instead it attempts to make a significant
  456. --- 111,122 ----
  457.      clearing the message, and should offer the possibility to
  458.      re-try the operation (which usually then works for us).
  459.   
  460. + There is a similar option [-y] to nnmaster which can be set to have
  461. + the nnmaster perform retries as well.
  462.   
  463.   
  464. ! TERMINAL I-O PROBLEMS
  465. ! ---------------------
  466.   
  467.   nn does not echo the characters you type except when you are entering
  468.   a string, e.g. a file name.  Instead it attempts to make a significant
  469. ***************
  470. *** 104,130 ****
  471.   change to the data displayed on the screen.  On a slow system this may
  472.   be seen as a drawback; on fast systems it is an intended feature!
  473.   
  474.   nn uses raw mode when reading from the keyboard and cooked mode when
  475. ! printing on the screen (it flips forth and back).  This has caused
  476.   problems on some systems (e.g. the 3B2) where the tty driver is
  477.   located on a dedicated IOprocessor, which for some reason handles
  478.   ioctl's "out of band".  I have tried to work around these problems by
  479.   outputting \r\n sequences where \n should have been sufficient.
  480.   
  481. ! nn also intentionally discards type-ahead at certain points.
  482.   
  483.   On some systems, TCSETAF also flushes the output queue; you may try to
  484.   replace it by TCSETAW followed by TCFLSH.
  485.   
  486.   
  487. ! NNMASTER WILL NOT START
  488. ! -----------------------
  489.   
  490.   If no nnmaster is running, and nnmaster refuses to start up, you
  491.   should check for the existence of the MPID file in the LIB directory,
  492.   If it exists, it should be removed.
  493.   
  494.   
  495.   WARNINGS DURING COMPILATION
  496.   ---------------------------
  497.   
  498. --- 123,184 ----
  499.   change to the data displayed on the screen.  On a slow system this may
  500.   be seen as a drawback; on fast systems it is an intended feature!
  501.   
  502. + If CBREAK is available, nn will use it, but when CBREAK is not avaiable
  503.   nn uses raw mode when reading from the keyboard and cooked mode when
  504. ! printing on the screen (it flips forth and back).  [This behaviour can
  505. ! be disabled by unsetting the flow-control variable]  This has caused
  506.   problems on some systems (e.g. the 3B2) where the tty driver is
  507.   located on a dedicated IOprocessor, which for some reason handles
  508.   ioctl's "out of band".  I have tried to work around these problems by
  509.   outputting \r\n sequences where \n should have been sufficient.
  510.   
  511. ! nn also intentionally discards type-ahead at certain points, but only
  512. ! if CBREAK mode is not supported, and the flow-control variable is set.
  513.   
  514.   On some systems, TCSETAF also flushes the output queue; you may try to
  515.   replace it by TCSETAW followed by TCFLSH.
  516.   
  517. + On terminals where the left arrow key sends a backspace (such as
  518. + Wyse50), the backspace key will not properly work as the erase key.
  519. + To circumvent this problem on these terminals, place the following
  520. + line in your init file:
  521. +     set erase-key left
  522. + Cnews
  523. + ------
  524. + nn wants articles to contain Lines: headers, but Cnews doesn't
  525. + generate these in the default setup.  You may uncomment the
  526. + Lines: code in the inews script.
  527. + As distributed, Cnews does not maintain the 'min' value in the active
  528. + file - there is a program named `upact' to do this.  Without it, 
  529. + expire on the database will not be performed.  One of the Cnews
  530. + patches is said to have changed this, but check it out.
  531.   
  532. ! NNMASTER WILL NOT START OR IS LOOPING
  533. ! -------------------------------------
  534.   
  535.   If no nnmaster is running, and nnmaster refuses to start up, you
  536.   should check for the existence of the MPID file in the LIB directory,
  537.   If it exists, it should be removed.
  538.   
  539. + If nnmaster starts looping, you should check the permissions on the
  540. + LIB directory and notice if a GATE file exists which nnmaster is not
  541. + allowed to unlink.
  542.   
  543. + NNMASTER DIES WHEN STARTED FROM A TERMINAL
  544. + ------------------------------------------
  545. + The definition DETATCH_TERMINAL in the s- file you use may not work
  546. + (it is a no-op on some systems).  This will cause a hangup signal to
  547. + be sent to the master when you logout, and that will terminate the
  548. + master.
  549.   WARNINGS DURING COMPILATION
  550.   ---------------------------
  551.   
  552. ***************
  553. *** 138,144 ****
  554.   
  555.   If the linker complains about not finding the function `strcspn'
  556.   (whice should be in most standard libraries these days), define the
  557. ! symbol STRCSPN in config.h to use the version in regexp.c.
  558.   
  559.   
  560.   FORMATTING THE MANUALS
  561. --- 192,199 ----
  562.   
  563.   If the linker complains about not finding the function `strcspn'
  564.   (whice should be in most standard libraries these days), define the
  565. ! symbol STRCSPN in the m- file (or config.h) to use the version in
  566. ! regexp.c.
  567.   
  568.   
  569.   FORMATTING THE MANUALS
  570. ***************
  571. *** 162,173 ****
  572.   NNMASTER AND NN DOES NOT FIND ANY NEWS
  573.   --------------------------------------
  574.   
  575. ! This problem has been seen on some Xenix ports.  I have not had the
  576. ! time to dig further into this problem.  If you succeeds in porting nn
  577. ! to Xenix (286/386), send me the patches + s- and m- files.
  578.   
  579. ! In release 6.3, some changes to the way files are opened may solve
  580. ! this problem, but I have not tested 6.3 on Xenix.
  581.   
  582.   
  583.   THE DATABASE BECOMES CORRUPTED FOR NO APPARENT REASON
  584. --- 217,226 ----
  585.   NNMASTER AND NN DOES NOT FIND ANY NEWS
  586.   --------------------------------------
  587.   
  588. ! All known occurrences of this problem have been identified and fixed.
  589.   
  590. ! Be careful about the 'limit' and 'old' variables.  Setting them in the
  591. ! init file may cause nn to behave strangely (as documented :-)
  592.   
  593.   
  594.   THE DATABASE BECOMES CORRUPTED FOR NO APPARENT REASON
  595. ***************
  596. *** 191,197 ****
  597. --- 244,253 ----
  598.     this problem sorted out (or determined that there isn't a bug), the
  599.     use of -E on the nnmaster is recommended.
  600.   
  601. + - nn release 6.3 patch #4 introduced a new 'misinterpretation' of the
  602. +   database.  It is fixed in patch #5. 
  603.     
  604. +   
  605.   8 BIT SUPPORT
  606.   -------------
  607.   
  608. ***************
  609. *** 238,245 ****
  610.   
  611.   The 'master flags' set on a group with nnadmin are forgotten if the
  612.   database is reinitialized with nnmaster -I.
  613. - The article selections saved between sessions are kept in a machine
  614. - dependent format, so if a user reads news on different architectures
  615. - the selection files may be misinterpreted if they cannot be ignored
  616. - (there is a magic number in them).
  617. --- 294,296 ----
  618. *** /usr/storm/nn6.3.0/Makefile    Thu Jun  1 11:10:40 1989
  619. --- Makefile    Fri Sep  8 12:46:40 1989
  620. ***************
  621. *** 29,34 ****
  622. --- 29,37 ----
  623.   all: ymakefile
  624.       $(MAKE) $(MFLAGS) -f ymakefile all
  625.   
  626. + nn: ymakefile
  627. +     $(MAKE) $(MFLAGS) -f ymakefile nn
  628.   lint: ymakefile
  629.       $(MAKE) -f ymakefile lint
  630.   
  631. *** /usr/storm/nn6.3.0/aux.sh    Thu Jun  1 11:10:41 1989
  632. --- aux.sh    Fri Sep  8 12:46:41 1989
  633. ***************
  634. *** 17,23 ****
  635.   # $1 is ident, $2 is group name.
  636.   
  637.   if [ "$OPERATION" = "cancel" ] ; then
  638. !     $INEWS -t 'cmsg cancel '"$1" -n "$2" < /dev/null > /tmp/nn$$c 2>&1
  639.       x=$?
  640.       if [ $x != 0 ]; then
  641.           echo ''
  642. --- 17,30 ----
  643.   # $1 is ident, $2 is group name.
  644.   
  645.   if [ "$OPERATION" = "cancel" ] ; then
  646. !     $INEWS -h  << EOF > /tmp/nn$$c 2>&1
  647. ! Newsgroups: $2
  648. ! Subject: cancel $1
  649. ! Control: cancel $1
  650. ! cancel $1 in newsgroup $2
  651. ! EOF
  652. ! #    $INEWS -t 'cmsg cancel '"$1" -n "$2" < /dev/null > /tmp/nn$$c 2>&1
  653.       x=$?
  654.       if [ $x != 0 ]; then
  655.           echo ''
  656. ***************
  657. *** 48,54 ****
  658.   while $loop ; do
  659.       if $prompt ; then
  660.           echo ''
  661. !         awk 'END{printf "Action: (a)bort (e)dit (o)k (s)end: "}' < /dev/null
  662.           read act
  663.       else
  664.           act="${FIRST_ACTION}"
  665. --- 55,61 ----
  666.   while $loop ; do
  667.       if $prompt ; then
  668.           echo ''
  669. !         awk 'END{printf "Action: (a)bort (e)dit (o)k (s)end (w)rite: "}' < /dev/null
  670.           read act
  671.       else
  672.           act="${FIRST_ACTION}"
  673. ***************
  674. *** 88,93 ****
  675. --- 95,107 ----
  676.           loop=false
  677.           ;;
  678.   
  679. +     w*)
  680. +         echo "Append article to file:"
  681. +         read FNAME
  682. +         if [ -n "$FNAME" ] ; then
  683. +             { cat $WORK ; echo ; } >> $FNAME
  684. +         fi
  685. +         ;;
  686.       esac
  687.   done
  688.   
  689. *** /usr/storm/nn6.3.4/collect.c    Mon Jul 10 13:36:04 1989
  690. --- collect.c    Fri Sep  8 12:46:41 1989
  691. ***************
  692. *** 2,7 ****
  693. --- 2,9 ----
  694.   #include "db.h"
  695.   #include "news.h"
  696.   
  697. + #define COUNT_RE_REFERENCES    /* no of >>> depends on Reference: line */
  698.   import int trace;
  699.   
  700.   
  701. ***************
  702. *** 151,158 ****
  703.           else
  704.           nextg = "";
  705.           
  706. !         if (strcmp(gh->group_name, curg) == 0) break;
  707.           if ((gh1 = lookup(curg)) == NULL) continue;
  708.   
  709.           *cp_ptr++ = gh1->group_num;
  710. --- 153,161 ----
  711.           else
  712.           nextg = "";
  713.           
  714. !         if (strcmp(gh->group_name, curg) == 0) /* break; */
  715. !         gh1 = gh;
  716. !         else
  717.           if ((gh1 = lookup(curg)) == NULL) continue;
  718.   
  719.           *cp_ptr++ = gh1->group_num;
  720. ***************
  721. *** 254,259 ****
  722. --- 257,271 ----
  723.       /* write subject line on .nn2 */
  724.   
  725.       hdr.dh_subject_length = pack_subject(subj_buf, subj, &re, 255);
  726. + #ifdef COUNT_RE_REFERENCES
  727. +     if (re) re = 0x80;
  728. +     if (news.ng_ref) {
  729. +     for (name = news.ng_ref; *name; name++) {
  730. +         if ((re & 0x7f) == 0x7f) break;
  731. +         if (*name == '<') re++;
  732. +     }
  733. +     }    
  734. + #endif
  735.       hdr.dh_replies = re;
  736.   
  737.       if (use_digest & 2) hdr.dh_subject_length++;    /* @ */
  738. *** /usr/storm/nn6.3.0/config.h-dist    Thu Jun  1 11:10:41 1989
  739. --- config.h-dist    Fri Sep  8 12:46:41 1989
  740. ***************
  741. *** 63,68 ****
  742. --- 63,79 ----
  743.   
  744.   #define NNTP_SERVER    "/usr/lib/nntp_server"
  745.   
  746. + /*
  747. +  *    Define NNTP_POST if you want nn to reject attempts to post via
  748. +  *    NNTP to a server, that disallows postings.
  749. +  *
  750. +  *    You should define this, if you use the NNTP based inews for
  751. +  *    postings from NNTP clients.  If you use another mechanism, that
  752. +  *    does not involve NNTP, you should leave it undefined.
  753. +  */
  754. + #define NNTP_POST             /* */
  755.   
  756.   /***************** OPERATING SYSTEM DEPENDENT DEFINITIONS *******************
  757.    *
  758. *** /usr/storm/nn6.3.4/data.h    Mon Jul 10 13:36:05 1989
  759. --- data.h    Fri Sep  8 12:46:41 1989
  760. ***************
  761. *** 36,43 ****
  762. --- 36,48 ----
  763.   
  764.       int32        group_flag;
  765.   
  766. + #ifdef I286_BUG
  767. + #    define MF(n)    (1L<<(n-1))
  768. + #    define CF(n)    (1L<<(n+15))
  769. + #else
  770.   #    define MF(n)    (((int32)1)<<(n-1))
  771.   #    define CF(n)    (((int32)1)<<(n+15))
  772. + #endif
  773.   
  774.   #    define G_MASTER_FLAGS    (MF(17)-1) /* flags that are saved on file */
  775.   
  776. ***************
  777. *** 70,75 ****
  778. --- 75,81 ----
  779.       /* AFTER THE PART WHICH IS SAVED IN THE MASTER FILE */
  780.   
  781.       group_number    group_num;
  782. +     group_number    preseq_index;
  783.   
  784.       char *        group_name;
  785.       
  786. ***************
  787. *** 118,123 ****
  788. --- 124,132 ----
  789.       int16    replies;    /*   no of Re:            */
  790.       int16    lines;        /*   no of lines        */
  791.   
  792. +     int8    subj_length;    /*   length of subject        */
  793. +     int8    name_length;    /*   length of sender        */
  794. +     
  795.       group_header *a_group;    /* if merged article menu    */
  796.       
  797.       int32    flag;        /* flags:             */
  798. *** /usr/storm/nn6.3.2/decode.c    Wed Jun 28 19:09:17 1989
  799. --- decode.c    Fri Sep  8 12:46:42 1989
  800. ***************
  801. *** 10,15 ****
  802. --- 10,17 ----
  803.   
  804.   #include "config.h"
  805.   
  806. + export char *decode_header_file = "Decode.Headers";
  807.   #define MAXCHAR 256
  808.   #define LINELEN 256
  809.   #define NORMLEN 60    /* allows for 80 encoded chars per line */
  810. ***************
  811. *** 117,122 ****
  812. --- 119,127 ----
  813.               goto err;
  814.           }
  815.           chmod(ofname, mode);
  816. +         if (decode_header_file)
  817. +             store_header(ah, in, target, decode_header_file);
  818.   
  819.           msg("Decoding: %s", ofname);
  820.           state = DECODE_TEXT;
  821. *** /usr/storm/nn6.3.0/digest.c    Thu Jun  1 11:10:42 1989
  822. --- digest.c    Fri Sep  8 12:46:42 1989
  823. ***************
  824. *** 115,120 ****
  825. --- 115,122 ----
  826.    * expect that f is positioned at header of an article
  827.    */
  828.   
  829. + static int is_mmdf_folder = 0;
  830.   get_digest_article(f, hdrbuf)
  831.   FILE *f;
  832.   news_header_buffer hdrbuf;
  833. ***************
  834. *** 211,216 ****
  835. --- 213,224 ----
  836.       if (fgets(line, 1024, f) == NULL) {
  837.       TEST("end_of_file, bc=%d, lines=%d\n", backup_count, digest.dg_lines);
  838.       
  839. +     if (is_mmdf_folder) {
  840. +         digest.dg_lpos = backup_p[backup_index];
  841. +         is_mmdf_folder = 0;
  842. +         return 0;
  843. +     }
  844. +     
  845.       /* end of file => look for "****" or "End of" line */
  846.   
  847.       if (end_or_asterisks)
  848. ***************
  849. *** 235,240 ****
  850. --- 243,258 ----
  851.       }
  852.   
  853.       TEST("\n>>%-.50s ==>>", line, 0);
  854. +     if (line[0] == '\001' && strcmp(line, "\001\001\001\001\n") == 0) {
  855. +     digest.dg_lpos = backup_p[backup_index];
  856. +     if (!is_mmdf_folder) fseek(f, digest.dg_lpos, 0);
  857. +     --digest.dg_lines;
  858. +     is_mmdf_folder = 0;
  859. +     return (digest.dg_lines <= 0) ? -1 : 1;
  860. +     }
  861. +         
  862. +     if (is_mmdf_folder) goto next_line;
  863.       
  864.       for (cp = line; *cp && isascii(*cp) && isspace(*cp); cp++);
  865.   
  866. ***************
  867. *** 310,316 ****
  868.   
  869.           if (digest.dg_lines == 0) {
  870.           TEST("Skipped empty article\n", 0, 0);
  871. !         return 0;
  872.           }
  873.           
  874.           for (;;) {
  875. --- 328,334 ----
  876.   
  877.           if (digest.dg_lines == 0) {
  878.           TEST("Skipped empty article\n", 0, 0);
  879. !         return -1;
  880.           }
  881.           
  882.           for (;;) {
  883. ***************
  884. *** 362,367 ****
  885. --- 380,393 ----
  886.       
  887.       switch (*lp++) {
  888.   
  889. +      case '\001':
  890. +     if (!is_mmdf_folder && strncmp(lp, "\001\001\001\n", 4) == 0) {
  891. +         is_mmdf_folder = 1;
  892. +         digest.dg_hpos += 5;
  893. +         return NULL;
  894. +     }
  895. +     break;
  896. +     
  897.        case 'D':
  898.        case 'd':    
  899.       check("ate: ",    5, dg_date);
  900. *** /usr/storm/nn6.3.4/execute.c    Mon Jul 10 13:36:06 1989
  901. --- execute.c    Fri Sep  8 12:46:42 1989
  902. ***************
  903. *** 15,21 ****
  904.   char *path, **args;
  905.   {
  906.       int was_raw, pid, i, status;
  907. !     sig_type  (*quit)(), (*intr)(), (*cont)();
  908.       extern int errno;
  909.       
  910.       was_raw = unset_raw();
  911. --- 15,21 ----
  912.   char *path, **args;
  913.   {
  914.       int was_raw, pid, i, status;
  915. !     sig_type  (*quit)(), (*intr)(), (*tstp)();
  916.       extern int errno;
  917.       
  918.       was_raw = unset_raw();
  919. ***************
  920. *** 34,40 ****
  921.       quit = signal(SIGQUIT, SIG_IGN);
  922.       intr = signal(SIGINT,  SIG_IGN);
  923.   #ifdef HAVE_JOBCONTROL
  924. !     cont = signal(SIGCONT, SIG_DFL);
  925.   #endif
  926.       while ((i = wait(&status)) != pid && (i != -1 || errno == EINTR));
  927.       
  928. --- 34,40 ----
  929.       quit = signal(SIGQUIT, SIG_IGN);
  930.       intr = signal(SIGINT,  SIG_IGN);
  931.   #ifdef HAVE_JOBCONTROL
  932. !     tstp = signal(SIGTSTP, SIG_DFL);
  933.   #endif
  934.       while ((i = wait(&status)) != pid && (i != -1 || errno == EINTR));
  935.       
  936. ***************
  937. *** 41,47 ****
  938.       signal(SIGQUIT, quit);
  939.       signal(SIGINT,  intr);
  940.   #ifdef HAVE_JOBCONTROL
  941. !     signal(SIGCONT, cont);
  942.   #endif
  943.       
  944.       if (was_raw) raw();
  945. --- 41,47 ----
  946.       signal(SIGQUIT, quit);
  947.       signal(SIGINT,  intr);
  948.   #ifdef HAVE_JOBCONTROL
  949. !     signal(SIGTSTP, tstp);
  950.   #endif
  951.       
  952.       if (was_raw) raw();
  953. ***************
  954. *** 88,94 ****
  955.       
  956.   run_shell(command, clear)
  957.   char *command;
  958. ! int clear;
  959.   {
  960.       char cmdstring[512];
  961.       
  962. --- 88,94 ----
  963.       
  964.   run_shell(command, clear)
  965.   char *command;
  966. ! int clear;    /* -1 => no output, 0 => CR/NL, 1 => clear */
  967.   {
  968.       char cmdstring[512];
  969.       
  970. ***************
  971. *** 95,104 ****
  972.       if (!expand_file_name(cmdstring, command))
  973.       return 0;
  974.       
  975. !     if (clear) {
  976.       clrdisp();
  977.       fl;
  978. !     } else {
  979.       putchar(CR);
  980.       putchar(NL);
  981.       }
  982. --- 95,104 ----
  983.       if (!expand_file_name(cmdstring, command))
  984.       return 0;
  985.       
  986. !     if (clear > 0) {
  987.       clrdisp();
  988.       fl;
  989. !     } else if (clear == 0) {
  990.       putchar(CR);
  991.       putchar(NL);
  992.       }
  993. ***************
  994. *** 124,136 ****
  995.       was_raw = unset_raw();
  996.       gotoxy(0, Lines-1);
  997.       clrline();
  998.   #ifdef HAVE_JOBCONTROL
  999. !     kill(process_id, SIGTSTP);
  1000.   #else
  1001.       execute(user_shell, exec_suspend_args);
  1002.   #endif
  1003.   
  1004.       s_redraw++;
  1005.       if (was_raw) raw();
  1006.       
  1007. --- 124,138 ----
  1008.       was_raw = unset_raw();
  1009.       gotoxy(0, Lines-1);
  1010.       clrline();
  1011. !     visual_off();
  1012. !     
  1013.   #ifdef HAVE_JOBCONTROL
  1014. !     kill(process_id, SIGSTOP);
  1015.   #else
  1016.       execute(user_shell, exec_suspend_args);
  1017.   #endif
  1018.   
  1019. +     visual_on();
  1020.       s_redraw++;
  1021.       if (was_raw) raw();
  1022.       
  1023. *** /usr/storm/nn6.3.4/global.c    Mon Jul 10 13:36:09 1989
  1024. --- global.c    Fri Sep  8 12:46:42 1989
  1025. ***************
  1026. *** 15,20 ****
  1027. --- 15,46 ----
  1028.   
  1029.   export int is_master;
  1030.   
  1031. + #ifdef HAVE_MULTIGROUP
  1032. + #ifndef NGROUPS
  1033. + #include <sys/param.h>
  1034. + #endif
  1035. + #ifndef GIDSET_TYPE
  1036. + #define GIDSET_TYPE int
  1037. + #endif
  1038. + static int ngroups;
  1039. + static GIDSET_TYPE gidset[NGROUPS];
  1040. + static in_grplist(gid)
  1041. + GIDSET_TYPE gid;
  1042. + {
  1043. +     int n;
  1044. +   
  1045. +     for (n = 0; n < ngroups; ++n)
  1046. +     if (gidset[n] == gid) return 1;
  1047. +     return 0;
  1048. + }
  1049. + #define group_access(gpid)    in_grplist((GIDSET_TYPE)(gpid))
  1050. + #else
  1051. + #define group_access(gid)    ((gid) == group_id)
  1052. + #endif
  1053. +    
  1054.   /* signal handler interface */
  1055.   
  1056.   export int s_hangup        = 0;    /* hangup signal */
  1057. ***************
  1058. *** 48,54 ****
  1059.   }
  1060.   
  1061.   #ifdef HAVE_JOBCONTROL
  1062. ! static sig_type catch_redraw(n)
  1063.   {
  1064.       s_redraw++;
  1065.   
  1066. --- 74,80 ----
  1067.   }
  1068.   
  1069.   #ifdef HAVE_JOBCONTROL
  1070. ! static sig_type catch_suspend(n)
  1071.   {
  1072.       s_redraw++;
  1073.   
  1074. ***************
  1075. *** 55,60 ****
  1076. --- 81,88 ----
  1077.   #ifdef RESET_SIGNAL_WHEN_CAUGHT
  1078.       signal(n, catch_redraw);
  1079.   #endif
  1080. +     suspend_nn();
  1081.   }
  1082.   #endif
  1083.   
  1084. ***************
  1085. *** 72,77 ****
  1086. --- 100,106 ----
  1087.       char *env;
  1088.       unsigned short getuid(), getgid();
  1089.       int getpid();
  1090. +     int suspend_nn();
  1091.   
  1092.       is_master = (who == 1);
  1093.       
  1094. ***************
  1095. *** 85,91 ****
  1096. --- 114,127 ----
  1097.   #endif
  1098.   
  1099.       user_id = getuid();
  1100. + #ifdef HAVE_MULTIGROUP
  1101. +     ngroups = getgroups(NGROUPS, gidset);    /* Get users's group set */
  1102. +     group_id = gidset[0];    /* not used, but just in case... */
  1103. + #else
  1104.       group_id = getgid();
  1105. + #endif
  1106.       process_id = getpid();
  1107.       
  1108.       if (is_master) {
  1109. ***************
  1110. *** 97,103 ****
  1111.       signal(SIGINT,  catch_keyboard);
  1112.       signal(SIGQUIT, catch_keyboard);
  1113.   #ifdef HAVE_JOBCONTROL
  1114. !     signal(SIGCONT, catch_redraw);
  1115.   #endif    
  1116.   
  1117.       if ((home_directory = getenv("HOME")) == NULL) 
  1118. --- 133,139 ----
  1119.       signal(SIGINT,  catch_keyboard);
  1120.       signal(SIGQUIT, catch_keyboard);
  1121.   #ifdef HAVE_JOBCONTROL
  1122. !     signal(SIGTSTP, catch_suspend);
  1123.   #endif    
  1124.   
  1125.       if ((home_directory = getenv("HOME")) == NULL) 
  1126. ***************
  1127. *** 317,333 ****
  1128.           break;
  1129.       case 'r':
  1130.           if ((statb.st_mode & 0400) && statb.st_uid == user_id) continue;
  1131. !         if ((statb.st_mode & 0040) && statb.st_gid == group_id) continue;
  1132.               if ((statb.st_mode & 0004)) continue;
  1133.           break;
  1134.       case 'w':
  1135.           if ((statb.st_mode & 0200) && statb.st_uid == user_id) continue;
  1136. !         if ((statb.st_mode & 0020) && statb.st_gid == group_id) continue;
  1137.               if ((statb.st_mode & 0002)) continue;
  1138.           break;
  1139.       case 'x':
  1140.           if ((statb.st_mode & 0100) && statb.st_uid == user_id) continue;
  1141. !         if ((statb.st_mode & 0010) && statb.st_gid == group_id) continue;
  1142.               if ((statb.st_mode & 0001)) continue;
  1143.           break;
  1144.       }        
  1145. --- 353,369 ----
  1146.           break;
  1147.       case 'r':
  1148.           if ((statb.st_mode & 0400) && statb.st_uid == user_id) continue;
  1149. !         if ((statb.st_mode & 0040) && group_access(statb.st_gid)) continue;
  1150.               if ((statb.st_mode & 0004)) continue;
  1151.           break;
  1152.       case 'w':
  1153.           if ((statb.st_mode & 0200) && statb.st_uid == user_id) continue;
  1154. !         if ((statb.st_mode & 0020) && group_access(statb.st_gid)) continue;
  1155.               if ((statb.st_mode & 0002)) continue;
  1156.           break;
  1157.       case 'x':
  1158.           if ((statb.st_mode & 0100) && statb.st_uid == user_id) continue;
  1159. !         if ((statb.st_mode & 0010) && group_access(statb.st_gid)) continue;
  1160.               if ((statb.st_mode & 0001)) continue;
  1161.           break;
  1162.       }        
  1163. ***************
  1164. *** 397,402 ****
  1165. --- 433,441 ----
  1166.   sys_error(va_alist)
  1167.   va_dcl
  1168.   {
  1169. +     char buf[512];
  1170. +     char *fmt;
  1171. +     FILE *f;
  1172.       va_list ap;
  1173.   
  1174.       va_start(ap);
  1175. ***************
  1176. *** 404,425 ****
  1177.       va_end(ap);
  1178.   
  1179.       if (is_master) {
  1180. - #ifndef HAVE_SYSLOG
  1181. -     FILE *f;
  1182. -     
  1183. -     f = open_file("/dev/console", OPEN_CREATE);
  1184. -     if (f == NULL) nn_exit(8);
  1185. -     fprintf(f, "\n\rNNMASTER FATAL ERROR\n\r");
  1186. -     fclose(f);
  1187. - #else /* HAVE_SYSLOG */
  1188. -     char buf[512];
  1189. -     char *fmt;
  1190.       va_start(ap);
  1191.       fmt = va_arg1(char *);
  1192.       vsprintf(buf, fmt, va_args2toN);
  1193.       va_end(ap);
  1194.   
  1195.       openlog("nnmaster", LOG_CONS, LOG_DAEMON);
  1196.       syslog(LOG_ALERT, "%s", buf);
  1197.       closelog();
  1198. --- 443,459 ----
  1199.       va_end(ap);
  1200.   
  1201.       if (is_master) {
  1202.       va_start(ap);
  1203.       fmt = va_arg1(char *);
  1204.       vsprintf(buf, fmt, va_args2toN);
  1205.       va_end(ap);
  1206.   
  1207. + #ifndef HAVE_SYSLOG
  1208. +     f = open_file("/dev/console", OPEN_CREATE);
  1209. +     if (f == NULL) nn_exit(8);
  1210. +     fprintf(f, "\n\rNNMASTER FATAL ERROR\n\r%s\n\n\r", buf);
  1211. +     fclose(f);
  1212. + #else /* HAVE_SYSLOG */
  1213.       openlog("nnmaster", LOG_CONS, LOG_DAEMON);
  1214.       syslog(LOG_ALERT, "%s", buf);
  1215.       closelog();
  1216. *** /usr/storm/nn6.3.0/global.h    Thu Jun  1 11:10:43 1989
  1217. --- global.h    Fri Sep  8 12:46:43 1989
  1218. ***************
  1219. *** 26,35 ****
  1220.   
  1221.   #define fl fflush(stdout)
  1222.   
  1223. ! #ifdef CTRL
  1224. ! #undef CTRL
  1225.   #endif
  1226. ! #define CTRL(c)    (c&037)
  1227.   
  1228.   #ifndef HAVE_STRCHR
  1229.   #define    strrchr        rindex
  1230. --- 26,35 ----
  1231.   
  1232.   #define fl fflush(stdout)
  1233.   
  1234. ! #ifdef CONTROL_
  1235. ! #undef CONTROL_
  1236.   #endif
  1237. ! #define CONTROL_(c)    (c&037)
  1238.   
  1239.   #ifndef HAVE_STRCHR
  1240.   #define    strrchr        rindex
  1241. ***************
  1242. *** 40,45 ****
  1243. --- 40,49 ----
  1244.   typedef void sig_type;
  1245.   #else
  1246.   typedef int sig_type;
  1247. + #endif
  1248. + #ifndef NNTP
  1249. + #undef NNTP_POST
  1250.   #endif
  1251.   
  1252.   /*
  1253. *** /usr/storm/nn6.3.4/group.c    Mon Jul 10 13:36:10 1989
  1254. --- group.c    Fri Sep  8 12:46:43 1989
  1255. ***************
  1256. *** 16,21 ****
  1257. --- 16,22 ----
  1258.   export int  dont_split_digests = 0;
  1259.   export int  dont_sort_articles = 0;
  1260.   export int  also_cross_postings = 0;
  1261. + export int  seq_cross_filtering = 0;
  1262.   
  1263.   import int  article_limit, also_read_articles;
  1264.   import int  no_update;
  1265. ***************
  1266. *** 111,116 ****
  1267. --- 112,118 ----
  1268.   #define    DONT_SORT_ARTICLES    0x02
  1269.   #define    DONT_SPLIT_DIGESTS    0x04    /* only full digest */
  1270.   #define    ALSO_FULL_DIGEST    0x08    /* also full digest */
  1271. + #define EXTRA_ARTICLES        0x10    /* add to current menu */
  1272.   
  1273.   static access_group(gh, first_article, last_article, flags, submask, do_kill)
  1274.   register group_header    *gh;
  1275. ***************
  1276. *** 119,124 ****
  1277. --- 121,127 ----
  1278.   char         *submask;
  1279.   int        do_kill;
  1280.   {
  1281. +     group_header        *cpgh;
  1282.       FILE            *data;
  1283.       data_header            hdr;
  1284.       off_t              data_offset;
  1285. ***************
  1286. *** 132,139 ****
  1287.       static regexp        *subpattern = NULL;
  1288.       static char            subptext[80];
  1289.       
  1290. -     if (init_group(gh) <= 0) return -2;
  1291.       if (first_article < gh->first_l_article) 
  1292.       first_article = gh->first_l_article;
  1293.   
  1294. --- 135,140 ----
  1295. ***************
  1296. *** 168,174 ****
  1297.           subpattern = NULL;
  1298.       }
  1299.       
  1300. !     mark_memory(&mem_marker);
  1301.       
  1302.       ah = alloc_art();
  1303.   
  1304. --- 169,176 ----
  1305.           subpattern = NULL;
  1306.       }
  1307.       
  1308. !     if ((flags & EXTRA_ARTICLES) == 0)
  1309. !     mark_memory(&mem_marker);
  1310.       
  1311.       ah = alloc_art();
  1312.   
  1313. ***************
  1314. *** 211,218 ****
  1315.           cross_post = ntohl(cross_post);
  1316.   #endif
  1317.   #endif        
  1318. !         if (active_groups[cross_post].group_flag & G_SUBSCRIPTION)
  1319.               break;
  1320.           } while (--n > 0);
  1321.           if (n > 0) {
  1322.           if (IS_DIGEST_HEADER(hdr)) skip_digest++;
  1323. --- 213,231 ----
  1324.           cross_post = ntohl(cross_post);
  1325.   #endif
  1326.   #endif        
  1327. !         cpgh = &active_groups[cross_post];
  1328. !         if (cpgh == gh) {
  1329. !             if (seq_cross_filtering) continue;
  1330. !             if (n > 1)
  1331. !             fseek(data, (off_t)(sizeof(cross_post_number)*(n-1)), 1);
  1332. !             n = 0;
  1333.               break;
  1334. +         }
  1335. +         if (cpgh->group_flag & G_SUBSCRIPTION) {
  1336. +             if (!seq_cross_filtering) break;
  1337. +             if (cpgh->preseq_index > 0 &&
  1338. +             cpgh->preseq_index < gh->preseq_index) break;
  1339. +         }
  1340.           } while (--n > 0);
  1341.           if (n > 0) {
  1342.           if (IS_DIGEST_HEADER(hdr)) skip_digest++;
  1343. ***************
  1344. *** 238,244 ****
  1345.       
  1346.       mark_str(&str_marker);
  1347.       
  1348. !     if (hdr.dh_sender_length) {
  1349.       ah->sender = alloc_str((int)hdr.dh_sender_length);
  1350.       if (fread(ah->sender, sizeof(char), (int)hdr.dh_sender_length, data)
  1351.           != hdr.dh_sender_length) goto data_error;
  1352. --- 251,257 ----
  1353.       
  1354.       mark_str(&str_marker);
  1355.       
  1356. !     if (ah->name_length = hdr.dh_sender_length) {
  1357.       ah->sender = alloc_str((int)hdr.dh_sender_length);
  1358.       if (fread(ah->sender, sizeof(char), (int)hdr.dh_sender_length, data)
  1359.           != hdr.dh_sender_length) goto data_error;
  1360. ***************
  1361. *** 245,251 ****
  1362.       } else
  1363.       ah->sender = "";
  1364.       
  1365. !     if (hdr.dh_subject_length) {
  1366.       ah->subject = alloc_str((int)hdr.dh_subject_length);
  1367.       if (fread(ah->subject, sizeof(char), (int)hdr.dh_subject_length, data)
  1368.           !=  hdr.dh_subject_length) goto data_error;
  1369. --- 258,264 ----
  1370.       } else
  1371.       ah->sender = "";
  1372.       
  1373. !     if (ah->subj_length = hdr.dh_subject_length) {
  1374.       ah->subject = alloc_str((int)hdr.dh_subject_length);
  1375.       if (fread(ah->subject, sizeof(char), (int)hdr.dh_subject_length, data)
  1376.           !=  hdr.dh_subject_length) goto data_error;
  1377. ***************
  1378. *** 280,286 ****
  1379.   data_error:
  1380.       log_entry('E', "%s: data inconsistency", gh->group_name);
  1381.       fclose(data);
  1382. !     release_memory(&mem_marker);
  1383.       return -1;
  1384.       
  1385.   out:
  1386. --- 293,300 ----
  1387.   data_error:
  1388.       log_entry('E', "%s: data inconsistency", gh->group_name);
  1389.       fclose(data);
  1390. !     if ((flags & EXTRA_ARTICLES) == 0)
  1391. !     release_memory(&mem_marker);
  1392.       return -1;
  1393.       
  1394.   out:
  1395. ***************
  1396. *** 357,362 ****
  1397. --- 371,379 ----
  1398.       o_first_article = current_first_article;
  1399.       o_killed = killed_articles;
  1400.       mark_memory(&sel_marker);
  1401. +     if (init_group(gh) <= 0) menu_return( ME_NEXT );
  1402. +     m_invoke(-1);
  1403.       
  1404.   after_selection:
  1405.   
  1406. ***************
  1407. *** 363,368 ****
  1408. --- 380,390 ----
  1409.       did_selection = 0;
  1410.       killed_articles = 0;
  1411.   
  1412. +     /* don't lose (a few) new articles when reentering a read group */
  1413. +     /* (the user will expect the menu to be the same, and may overlook */
  1414. +     /* the new articles) */
  1415. +     if (gh->group_flag & G_READ) goto update_unsafe;
  1416. +     
  1417.       prev_last = gh->last_l_article;
  1418.   
  1419.       was_unread = add_unread(gh, -1);
  1420. ***************
  1421. *** 389,394 ****
  1422. --- 411,417 ----
  1423.       if (was_unread)
  1424.       add_unread(gh, 1);
  1425.   
  1426. +  update_unsafe:
  1427.       gotoxy(0, 0);
  1428.       fl;
  1429.   
  1430. ***************
  1431. *** 404,410 ****
  1432.       if (submask == NULL && !also_read_articles) {
  1433.           if (has_selection(gh, ¤t_first_article, &last_article)) {
  1434.           status = access_group(gh, current_first_article, last_article,
  1435. !                       DONT_SORT_ARTICLES, (char *)NULL, 0);
  1436.           do_selections(status >= 0 && n_articles);
  1437.           if (status < 0) goto access_exception;
  1438.           if (n_articles) {
  1439. --- 427,433 ----
  1440.       if (submask == NULL && !also_read_articles) {
  1441.           if (has_selection(gh, ¤t_first_article, &last_article)) {
  1442.           status = access_group(gh, current_first_article, last_article,
  1443. !                       access_mode | DONT_SORT_ARTICLES, (char *)NULL, 0);
  1444.           do_selections(status >= 0 && n_articles);
  1445.           if (status < 0) goto access_exception;
  1446.           if (n_articles) {
  1447. ***************
  1448. *** 449,457 ****
  1449.       menu_return( ME_NEXT );
  1450.       }
  1451.       
  1452. !     if (n_articles == 0)
  1453.       menu_return( ME_NO_ARTICLES );
  1454.    read_the_articles:
  1455.   
  1456.       menu_cmd = (*menu)(print_header);
  1457. --- 472,482 ----
  1458.       menu_return( ME_NEXT );
  1459.       }
  1460.       
  1461. !     if (n_articles == 0) {
  1462. !     m_break_entry();
  1463.       menu_return( ME_NO_ARTICLES );
  1464. !     }
  1465. !     
  1466.    read_the_articles:
  1467.   
  1468.       menu_cmd = (*menu)(print_header);
  1469. ***************
  1470. *** 683,691 ****
  1471.   
  1472.       m_advinput();
  1473.   
  1474. !     if (gh->last_l_article == 0 ||
  1475.       gh->last_l_article < gh->first_l_article) {
  1476. !     msg("Group %s is empty", answer);
  1477.       goto_return(ME_NO_REDRAW);
  1478.       }
  1479.   
  1480. --- 708,718 ----
  1481.   
  1482.       m_advinput();
  1483.   
  1484. !     if (gh->group_flag & G_BLOCKED ||
  1485. !     gh->last_l_article == 0 ||
  1486.       gh->last_l_article < gh->first_l_article) {
  1487. !     msg("Group %s is %s", answer, 
  1488. !         (gh->group_flag & G_BLOCKED) ? "blocked" : "empty");
  1489.       goto_return(ME_NO_REDRAW);
  1490.       }
  1491.   
  1492. ***************
  1493. *** 800,806 ****
  1494.       }
  1495.       
  1496.       if (access_group(gh, first, current_first_article - 1,
  1497. !                   ALSO_CROSS_POSTINGS, (char *)NULL, 0) < 0) {
  1498.           msg("Cannot read extra articles (now)");
  1499.           goto_return(ME_NO_REDRAW);
  1500.       }
  1501. --- 827,833 ----
  1502.       }
  1503.       
  1504.       if (access_group(gh, first, current_first_article - 1,
  1505. !              EXTRA_ARTICLES|ALSO_CROSS_POSTINGS, (char *)NULL, 0) < 0) {
  1506.           msg("Cannot read extra articles (now)");
  1507.           goto_return(ME_NO_REDRAW);
  1508.       }
  1509. ***************
  1510. *** 817,823 ****
  1511.   
  1512.       if (gh != orig_group) {
  1513.       current_first_article = o_current_first;
  1514. !     if (orig_group) init_group(orig_group);
  1515.       }
  1516.       
  1517.   goto_exit:
  1518. --- 844,850 ----
  1519.   
  1520.       if (gh != orig_group) {
  1521.       current_first_article = o_current_first;
  1522. !     if (orig_group) { init_group(orig_group); m_invoke(-1); }
  1523.       }
  1524.       
  1525.   goto_exit:
  1526. ***************
  1527. *** 849,855 ****
  1528.       if (dont_split_digests)
  1529.       access_mode |= DONT_SPLIT_DIGESTS;
  1530.       
  1531. !     for (cur = group_sequence; cur != NULL; cur = cur->next_group) {
  1532.       if (s_hangup || s_keyboard) break;
  1533.   
  1534.       if (cur->group_flag & G_FOLDER) {
  1535. --- 876,882 ----
  1536.       if (dont_split_digests)
  1537.       access_mode |= DONT_SPLIT_DIGESTS;
  1538.       
  1539. !     Loop_Groups_Sequence(cur) {
  1540.       if (s_hangup || s_keyboard) break;
  1541.   
  1542.       if (cur->group_flag & G_FOLDER) {
  1543. ***************
  1544. *** 863,868 ****
  1545. --- 890,896 ----
  1546.       
  1547.       printf("\r%s", cur->group_name); clrline();
  1548.       
  1549. +     if (init_group(cur) <= 0) continue;
  1550.       access_group(cur, (article_number)(-1), cur->last_l_article, access_mode, submask, do_kill);
  1551.       }
  1552.       merge_memory();
  1553. ***************
  1554. *** 926,931 ****
  1555. --- 954,970 ----
  1556.   
  1557.       pg_init(0, 2);
  1558.   
  1559. +     if (amount < 0) {
  1560. +     Loop_Groups_Sequence(gh) {
  1561. +         if (gh->group_flag & (G_READ | G_NO_DIRECTORY))
  1562. +         continue;
  1563. +         if ((gh->group_flag & G_SUBSCRIPTION) == 0)
  1564. +         continue;
  1565. +         if (gh->last_article >= gh->last_l_article)
  1566. +         continue;
  1567. +         if (disp_group(gh) < 0) break;
  1568. +     }
  1569. +     } else
  1570.       Loop_Groups_Sorted(gh) {
  1571.   
  1572.       if (gh->group_flag & G_NO_DIRECTORY) continue;
  1573. ***************
  1574. *** 939,951 ****
  1575.       if (amount == 3 && (gh->group_flag & G_SUBSCRIPTION))
  1576.           continue;
  1577.   
  1578. !     if (pg_next() < 0) break;
  1579. !     printf("%6ld %s%s",
  1580. !            (long)(gh->last_l_article - gh->last_article),
  1581. !            gh->group_name,
  1582. !            gh->group_flag & G_SUBSCRIPTION ? "" : " (!)");
  1583.       }
  1584.   
  1585.       pg_end();
  1586.   }
  1587. --- 978,1000 ----
  1588.       if (amount == 3 && (gh->group_flag & G_SUBSCRIPTION))
  1589.           continue;
  1590.   
  1591. !     if (disp_group(gh) < 0) break;
  1592.       }
  1593.   
  1594.       pg_end();
  1595.   }
  1596. + static disp_group(gh)
  1597. + group_header *gh;
  1598. + {
  1599. +     if (pg_next() < 0) return -1;
  1600. +     
  1601. +     printf("%6ld%c%s%s",
  1602. +        (long)(gh->last_l_article - gh->last_article),
  1603. +        (gh == current_group) ? '*' : ' ',
  1604. +        gh->group_name,
  1605. +        gh->group_flag & G_SUBSCRIPTION ? "" : " (!)");
  1606. +     return 0;
  1607. + }
  1608. +     
  1609. *** /usr/storm/nn6.3.0/help.commands    Thu Jun  1 11:10:43 1989
  1610. --- help.commands    Fri Sep  8 12:46:43 1989
  1611. ***************
  1612. *** 1,12 ****
  1613. --- 1,16 ----
  1614.   ;:ACOMMAND NAMES;:A                        ;:AMAP COMMAND;:A
  1615.   
  1616.   ;:BNAME        MENU    MORE    FUNCTION
  1617. + advance-article        A    advance to next article from menu
  1618.   advance-group    A         advance one group in sequence
  1619. + article N        a-z    select article N (0..no of menu lines-1)
  1620. + back-article        B    go back one article from menu
  1621.   back-group    B         go back one group in sequence
  1622.   cancel        C    C    cancel an article
  1623.   command        :    :    extenced command prefix
  1624.   compress        c    compress text (eliminate extra spaces)
  1625.   continue    SPACE    SPACE    the "space bar" command
  1626. + decode        :decode    :decode    decode uuencoded article(s)
  1627.   find            /    regular expression search
  1628.   find-next        .    repeat regular expression search
  1629.   follow        F     f F    follow up
  1630. ***************
  1631. *** 16,24 ****
  1632. --- 20,30 ----
  1633.   help        ?    ?    online help
  1634.   kill-select    K    K    kill/select handling
  1635.   layout        L        change menu layout
  1636. + leave-article    l    l    leave (mark) article for later use
  1637.   line+1        down    CR    next menu line/scroll one line 
  1638.   line-1        up        previous menu line
  1639.   line=@            g    goto specific line
  1640. + macro N                invoke macro number N (0..100)
  1641.   mail        M    m M    mail or forward
  1642.   message        ^P    ^P    repeat last prompt line message
  1643.   next-article        n    skip to next article
  1644. ***************
  1645. *** 34,43 ****
  1646.   page=0            h    goto header of article    
  1647.   page=1        ^    ^    goto first menu/article page
  1648.   page=@                goto specific page of article (not implemented)
  1649. ! post                post new article
  1650.   preview        %        preview article
  1651. ! previous    P    P    goto previous group/article
  1652. ! print            p    print article
  1653.   quit        Q    Q    quit nn
  1654.   read-return    Z        read selected articles and return to menu
  1655.   read-skip    X        read selected article, skip unseen menu pages
  1656. --- 40,50 ----
  1657.   page=0            h    goto header of article    
  1658.   page=1        ^    ^    goto first menu/article page
  1659.   page=@                goto specific page of article (not implemented)
  1660. ! patch        :patch    :patch    pipe article through patch program
  1661. ! post        :post    :post    post new article
  1662.   preview        %        preview article
  1663. ! previous    P    p    goto previous group/article
  1664. ! print        :print    P    print article
  1665.   quit        Q    Q    quit nn
  1666.   read-return    Z        read selected articles and return to menu
  1667.   read-skip    X        read selected article, skip unseen menu pages
  1668. *** /usr/storm/nn6.3.0/help.extended    Thu Jun  1 11:10:43 1989
  1669. --- help.extended    Fri Sep  8 12:46:43 1989
  1670. ***************
  1671. *** 2,19 ****
  1672.   
  1673.   :help COMMAND        give help on specific command
  1674.   
  1675. ! :q!            quit nn without update (only with -B option)
  1676.   :x            quit nn, mark current group as read
  1677.   
  1678. ! :mkdir [DIR]        create directory DIR (will prompt for DIR if omitted)
  1679. ! :cd [DIR]        change working directory to DIR
  1680.   
  1681.   :admin            enter administration mode
  1682. ! :set OPTION [VALUE]    set or unset option (use 'help set' for more info)
  1683. ! :map MODE KEY COMMAND    remap key or command
  1684. ! :show TABLE        show contents of various tables
  1685.   :sort MODE        sort menu according to subject, age, or arrival
  1686.   :unread (N)        mark current group as unread (last N articles)
  1687. ! :coredump        abort with a core dump
  1688. --- 2,28 ----
  1689.   
  1690.   :help COMMAND        give help on specific command
  1691.   
  1692. ! :q!            quit nn without update
  1693.   :x            quit nn, mark current group as read
  1694.   
  1695. ! :! SHELL-COMMAND    execute SHELL-COMMAND w/o screen redraw.
  1696.   
  1697.   :admin            enter administration mode
  1698. ! :cd [DIR]        change working directory to DIR
  1699. ! :compile        recompile & load kill file
  1700. ! :coredump        abort with a core dump
  1701. ! :decode            decode uuencoded article(s)
  1702. ! :define N ... end    define macro N
  1703. ! :man            read online manual
  1704. ! :map MODE KEY COMMAND    remap key or command (use ':help map' for more info)
  1705. ! :mkdir [DIR]        create directory DIR (will prompt for DIR if omitted)
  1706. ! :print            print article
  1707. ! :set VARIABLE [VALUE]    set or unset variable (use ':help set' for more info)
  1708. ! :show groups HOW    show group subscriptions etc.
  1709. ! :show kill        show kill file entries for current group
  1710. ! :show map MAP        show key mappings (MAP = #, key, menu, show)
  1711.   :sort MODE        sort menu according to subject, age, or arrival
  1712. ! :toggle VARIABLE    toggle boolean variable
  1713.   :unread (N)        mark current group as unread (last N articles)
  1714. ! :unset VARIABLE        clear variable
  1715. ! :unshar            unshar article(s)
  1716. *** /usr/storm/nn6.3.0/help.help    Thu Jun  1 11:10:43 1989
  1717. --- help.help    Fri Sep  8 12:46:43 1989
  1718. ***************
  1719. *** 1,8 ****
  1720.   ;:AHELP COMMAND;:A
  1721.   
  1722. ! Synopsis
  1723.   
  1724. !     :help subject
  1725.   
  1726.   Help is available on the the following subjects:
  1727.   
  1728. --- 1,8 ----
  1729.   ;:AHELP COMMAND;:A
  1730.   
  1731. ! :man        Read online manual
  1732.   
  1733. ! :help SUBJECT    Get help on specified SUBJECT
  1734.   
  1735.   Help is available on the the following subjects:
  1736.   
  1737. *** /usr/storm/nn6.3.0/help.map    Thu Jun  1 11:10:43 1989
  1738. --- help.map    Fri Sep  8 12:46:44 1989
  1739. ***************
  1740. *** 4,18 ****
  1741.   
  1742.   map menu KEY COMMAND    map KEY into COMMAND in menu mode
  1743.   map show KEY COMMAND    map KEY into COMMAND in article presentation mode
  1744.   map key  KEY1 KEY2    map KEY1 into KEY2 (unconditionally)
  1745.   map #N   CH1 CH2 ...    define the input sequence CH1 CH2 ... as special key N
  1746.   
  1747.   ;:AKEYS;:A
  1748.   
  1749. !     0xNN: the ascii character NN
  1750. !     C: the character C
  1751. !     ^C: control-C (^? = DEL)
  1752. !     #N: special key number N
  1753. !     up, down, left, rigth: the arrow keys
  1754.   
  1755.   ;:Chelp.commands
  1756. --- 4,27 ----
  1757.   
  1758.   map menu KEY COMMAND    map KEY into COMMAND in menu mode
  1759.   map show KEY COMMAND    map KEY into COMMAND in article presentation mode
  1760. + map both KEY COMMAND    map KEY into COMMAND in both modes
  1761.   map key  KEY1 KEY2    map KEY1 into KEY2 (unconditionally)
  1762.   map #N   CH1 CH2 ...    define the input sequence CH1 CH2 ... as special key N
  1763.   
  1764. + ;:ASPECIAL FORMS;:A  (TABLE = menu, show, both)
  1765. + map TABLE KEY1 as KEY2    map KEY1 into the command bound to KEY2
  1766. + map TABLE KEY macro N    map KEY to invoke macro number N
  1767. + map menu KEY article N    map KEY to select item number N (base 0) on the menu
  1768.   ;:AKEYS;:A
  1769.   
  1770. ! 0xNN    the ascii character NN
  1771. ! C    the character C
  1772. ! ^C    control-C 
  1773. ! ^?    DEL
  1774. ! #N    special key number N
  1775. ! up, down, left, rigth:  the arrow keys
  1776.   
  1777.   ;:Chelp.commands
  1778. *** /usr/storm/nn6.3.0/help.menu    Thu Jun  1 11:10:43 1989
  1779. --- help.menu    Fri Sep  8 12:46:44 1989
  1780. ***************
  1781. *** 1,22 ****
  1782.   ;:ASELECT (toggle);:A                ;:AMOVE;:A
  1783. ! a-z0-9    specified article        ,    Next menu line
  1784. ! x-y    range x to y            /    Previous menu line
  1785. ! x*    same subject as x        SPACE    Next menu page (if any)
  1786. ! .    current article            < >    Prev/Next menu page
  1787. ! @    Reverse all selections        ^ $    First/Last menu page
  1788.   ;:ASHOW SELECTED ARTICLES;:A
  1789.   SPACE    Show selected articles (only when on last menu page)
  1790.   Z     Show selected articles NOW, and return to this group afterwards
  1791.   X    Show selected articles NOW, and continue with next group
  1792.   ;:AGOTO OTHER GROUPS;:A
  1793.   X    If no articles are selected then skip to next group.
  1794.   N P     Goto next/previous group WITHOUT reading current group
  1795.   G    Goto named group or open a folder.
  1796.   B A    Go back/forward in groups already read
  1797.   ;:AMISCELLANEOUS;:A
  1798. ! U    (Un)subscribe            L    Change menu layout
  1799.   S O W    Save articles            !    Shell escape
  1800. ! F R M    Follow-up/Reply/Mail        C    Cancel an article of your own
  1801. --- 1,22 ----
  1802.   ;:ASELECT (toggle);:A                ;:AMOVE;:A
  1803. ! a-z0-9    Specified article        ,    Next menu line
  1804. ! x-y    Range x to y            /    Previous menu line
  1805. ! x*    Same subject as x        SPACE    Next menu page (if any)
  1806. ! .    Current article            < >    Prev/Next menu page
  1807. ! @ ~    Reverse/Undo all selections    ^ $    First/Last menu page
  1808. ! =regexp    Matching subjects
  1809.   ;:ASHOW SELECTED ARTICLES;:A
  1810.   SPACE    Show selected articles (only when on last menu page)
  1811.   Z     Show selected articles NOW, and return to this group afterwards
  1812.   X    Show selected articles NOW, and continue with next group
  1813.   ;:AGOTO OTHER GROUPS;:A
  1814.   X    If no articles are selected then skip to next group.
  1815.   N P     Goto next/previous group WITHOUT reading current group
  1816.   G    Goto named group or open a folder.
  1817.   B A    Go back/forward in groups already read
  1818.   ;:AMISCELLANEOUS;:A
  1819. ! Q    Quit nn                :help    More online help
  1820. ! U C    (Un)subscribe / Cancel        :man    Online manual
  1821. ! F R M    Follow-up/Reply/Mail        L    Change menu layout
  1822.   S O W    Save articles            !    Shell escape
  1823. ! :unshar :decode :patch    Unpack articles
  1824. *** /usr/storm/nn6.3.4/help.more    Mon Jul 10 13:36:11 1989
  1825. --- help.more    Fri Sep  8 12:46:44 1989
  1826. ***************
  1827. *** 14,20 ****
  1828.                                                   ;:AQUIT / ESCAPE;:A
  1829.   ;:ASAVE;:A                                   =       back to menu
  1830.   s, o, w   save with full/short/no header         N       goto next group
  1831. ! :unshar      unshar article            X       as N, mark as read
  1832.                                !, ^Z   Shell escape, suspend
  1833.   ;:AREPLY, POST;:A                    Q       quit nn
  1834.   r       mail reply to author of article                      
  1835. --- 14,20 ----
  1836.                                                   ;:AQUIT / ESCAPE;:A
  1837.   ;:ASAVE;:A                                   =       back to menu
  1838.   s, o, w   save with full/short/no header         N       goto next group
  1839. ! :unshar :decode :patch      unpack article    X       as N, mark as read
  1840.                                !, ^Z   Shell escape, suspend
  1841.   ;:AREPLY, POST;:A                    Q       quit nn
  1842.   r       mail reply to author of article                      
  1843. *** /usr/storm/nn6.3.0/help.variables    Thu Jun  1 11:10:44 1989
  1844. --- help.variables    Fri Sep  8 12:46:44 1989
  1845. ***************
  1846. *** 1,34 ****
  1847.   ;:AVARIABLES;:A
  1848.   
  1849. ! backup            Keep backup of rc file + delay update until quit (= -B)
  1850.   comp1-key KEY        Completion key 1 (space)
  1851.   comp2-key KEY        Completion key 2 (tab)
  1852. ! confirm            User must confirm all messages with return (= -W)
  1853. ! date              Show article dates (date = -D)
  1854. ! default-save-file FILE    Default save file (for + abbreviation)        
  1855.   delay-redraw        Do not redraw screen immediately after : commands
  1856.   erase-key KEY        Erase last input character or completion
  1857.   expert            Use shorter prompts
  1858.   folder DIR         Folder directory
  1859.   fsort            Sort folders in subject order (nofsort = -f)
  1860.   header-lines LIST    Customized article header format
  1861.   help-key KEY        Completion help key (?)
  1862.   included-mark STR      Prefix on included lines in replies (>) 
  1863.   kill            Enable/disable auto kill/select (nokill = -k)
  1864.   kill-key KEY        Delete input line key
  1865.   layout N        Menu layout N (-LN)
  1866.   limit N              Limit number of presented articles to N (-aN)
  1867.   long-menu        Use all lines on the menu screen
  1868.   macro-debug        Trace the execution of all macros
  1869.   mail-format        Folders are created in mail compatible format
  1870.   mail-record FILE      Save all replies in FILE
  1871.   monitor            Print all characters when reading article
  1872.   news-record FILE      Save all posted articles in FILE
  1873.   old   N              Show read articles also (-xN, or -x if N is omitted)
  1874.   overlap N        Display last N lines on next page when reading
  1875.   pager CMD          Screen pager used in administration mode (e.g. pg -n)
  1876.   printer CMD         Default print command (e.g. lp -s)
  1877.   quick-save        Save in default save file without asking
  1878.   record FILE          Set both news-record and mail-record to FILE
  1879.   repeat            Do not truncate repeated subject lines
  1880.   retry-on-error N    Retry N times if open of article fails
  1881. --- 1,57 ----
  1882.   ;:AVARIABLES;:A
  1883.   
  1884. ! Certain variables can be toggled with the specified command line options.
  1885. ! also-subgroups        Group names in sequence includes subgroups as well
  1886. ! backup            Keep backup of rc file (-B)
  1887. ! collapse-subject    Offset at which long subjects are compressed
  1888. ! columns            Screen width
  1889.   comp1-key KEY        Completion key 1 (space)
  1890.   comp2-key KEY        Completion key 2 (tab)
  1891. ! confirm-append        User must confirm saving in existing files
  1892. ! confirm-auto-quit    User must confirm quit after reading last group
  1893. ! confirm-messages    User must confirm all messages with return (-W)
  1894. ! cross-filter-seq    Show cross posted articles in first group in sequence
  1895. ! cross-post        Show cross posted articles in all groups (-X)
  1896. ! date              Show article dates (-D)
  1897. ! decode-header-file    Save file for headers of :decoded articles 
  1898. ! default-distribution DISTR  Default answer when asking for distribution
  1899. ! default-save-file FILE    Default save file (for + abbreviation)
  1900.   delay-redraw        Do not redraw screen immediately after : commands
  1901.   erase-key KEY        Erase last input character or completion
  1902.   expert            Use shorter prompts
  1903. + flow-control        Toggle between raw and cooked to enable flow control
  1904.   folder DIR         Folder directory
  1905.   fsort            Sort folders in subject order (nofsort = -f)
  1906.   header-lines LIST    Customized article header format
  1907.   help-key KEY        Completion help key (?)
  1908. + include-art-id        Include article-id in ".... writes:" line in follow-ups
  1909.   included-mark STR      Prefix on included lines in replies (>) 
  1910.   kill            Enable/disable auto kill/select (nokill = -k)
  1911.   kill-key KEY        Delete input line key
  1912.   layout N        Menu layout N (-LN)
  1913.   limit N              Limit number of presented articles to N (-aN)
  1914. + lines            Screen length
  1915.   long-menu        Use all lines on the menu screen
  1916.   macro-debug        Trace the execution of all macros
  1917. + mail            Mailbox file to check for arrival of new mail
  1918.   mail-format        Folders are created in mail compatible format
  1919. + mail-header STRING    Extra header lines to include in posted mail
  1920.   mail-record FILE      Save all replies in FILE
  1921. + mark-overlap        Underline last line from prev page to show overlap
  1922. + min-window        Minimum size of preview window, clear if smaller
  1923. + mmdf-format        Folders are written in MMDF format
  1924.   monitor            Print all characters when reading article
  1925. + news-header STRING    Extra header lines to include in posted articles
  1926.   news-record FILE      Save all posted articles in FILE
  1927. + newsrc            Maintain .newsrc file (not full compatibility)
  1928.   old   N              Show read articles also (-xN, or -x if N is omitted)
  1929.   overlap N        Display last N lines on next page when reading
  1930.   pager CMD          Screen pager used in administration mode (e.g. pg -n)
  1931. + patch-cmd        Command used by :patch command
  1932.   printer CMD         Default print command (e.g. lp -s)
  1933.   quick-save        Save in default save file without asking
  1934. + re-layout N        Presentation of Re: prefixes on menu subjects
  1935.   record FILE          Set both news-record and mail-record to FILE
  1936.   repeat            Do not truncate repeated subject lines
  1937.   retry-on-error N    Retry N times if open of article fails
  1938. ***************
  1939. *** 35,43 ****
  1940.   save-counter FMT      Format of the save counter (e.g. .%02d)
  1941.   save-report        Display number of lines saved
  1942.   silent            Do not print "No news" etc.
  1943. ! sort              Sort articles on menu (nosort = -q)
  1944. ! split              Split digests (nosplit = -d)
  1945. ! stop N            Stop printing of articles after N lines (= -lN)
  1946. ! time              Show current time on prompt line (notime = -T)
  1947. ! window N        Preview window size is N lines (= -wN)
  1948. --- 58,71 ----
  1949.   save-counter FMT      Format of the save counter (e.g. .%02d)
  1950.   save-report        Display number of lines saved
  1951.   silent            Do not print "No news" etc.
  1952. ! slow-mode        Minimize screen output
  1953. ! slow-speed SPEED    'on slow' clause is true for this and lower speeds
  1954. ! sort              Sort articles on menu (-q)
  1955. ! split              Split digests (-d)
  1956. ! stop N            Stop printing of articles after N lines (-lN)
  1957. ! time              Show current time on prompt line (-T)
  1958. ! unshar-header-file    Save file for headers from unshared articles
  1959. ! visible-bell        Use visible bell if defined in termcap/terminfo
  1960. ! window N        Preview window size is N lines (-wN)
  1961. ! word-key KEY        Delete last component (word) of input (^W)
  1962. ! wrap-header-margin    Fold long header lines over multiple lines
  1963. *** /usr/storm/nn6.3.0/help.welcome    Thu Jun  1 11:10:44 1989
  1964. --- help.welcome    Fri Sep  8 12:46:44 1989
  1965. ***************
  1966. *** 2,16 ****
  1967.   
  1968.   Unlike the other news readers you might be familiar with, the ultimate
  1969.   goal of nn is "not to read news"; actually, "nn" is an acronym for "No
  1970. ! News", and the parole for nn is:
  1971.   
  1972.       No news is good news, but nn is better.
  1973.   
  1974.   I hope that you will enjoy using nn.
  1975.   
  1976. ! If you have problems, try the '?' command which will provide a quick
  1977. ! reference guide for the present environment.  Otherwise, consult the
  1978. ! manuals or ask a local guru.  
  1979.   
  1980.   
  1981.   Have fun,
  1982. --- 2,16 ----
  1983.   
  1984.   Unlike the other news readers you might be familiar with, the ultimate
  1985.   goal of nn is "not to read news"; actually, "nn" is an acronym for "No
  1986. ! News", and the motto of nn is:
  1987.   
  1988.       No news is good news, but nn is better.
  1989.   
  1990.   I hope that you will enjoy using nn.
  1991.   
  1992. ! Three levels of online help is available: ;:A?;:A gives a quick reference 
  1993. ! guide for the current mode, ;:A:help;:A explains how to get help on specific
  1994. ! subjects, and ;:A:man;:A lets you read the online manual.
  1995.   
  1996.   
  1997.   Have fun,
  1998. *** /usr/storm/nn6.3.4/init.c    Mon Jul 10 13:36:12 1989
  1999. --- init.c    Fri Sep  8 12:46:44 1989
  2000. ***************
  2001. *** 38,49 ****
  2002.   }
  2003.   
  2004.       
  2005. ! visit_init_file()
  2006.   {
  2007.       extern FILE *loc_seq_hook, *glob_seq_hook;
  2008.       in_init = 1;
  2009. !     load_init_file(relative(lib_directory, "init"), &glob_seq_hook);
  2010. !     load_init_file("init", &loc_seq_hook);
  2011.       if (init_err) nn_exit(1);
  2012.       in_init = 0;
  2013.   }
  2014. --- 38,50 ----
  2015.   }
  2016.   
  2017.       
  2018. ! visit_init_file(only_seq)
  2019. ! int only_seq;
  2020.   {
  2021.       extern FILE *loc_seq_hook, *glob_seq_hook;
  2022.       in_init = 1;
  2023. !     load_init_file(relative(lib_directory, "init"), &glob_seq_hook, only_seq);
  2024. !     load_init_file("init", &loc_seq_hook, only_seq);
  2025.       if (init_err) nn_exit(1);
  2026.       in_init = 0;
  2027.   }
  2028. ***************
  2029. *** 52,58 ****
  2030.   #define START_SEQUENCE 555
  2031.   
  2032.   
  2033. ! static load_init_file(name, seq_hook_ptr)
  2034.   char *name;
  2035.   FILE **seq_hook_ptr;
  2036.   {
  2037. --- 53,59 ----
  2038.   #define START_SEQUENCE 555
  2039.   
  2040.   
  2041. ! static load_init_file(name, seq_hook_ptr, only_seq)
  2042.   char *name;
  2043.   FILE **seq_hook_ptr;
  2044.   {
  2045. ***************
  2046. *** 77,82 ****
  2047. --- 78,88 ----
  2048.       if (init == NULL) return;
  2049.   
  2050.       while (fgets(cmdbuf, 512, init)) {
  2051. +     if (only_seq) {
  2052. +         if (!is_sequence(cmdbuf)) continue;
  2053. +         *seq_hook_ptr = init;
  2054. +         return;
  2055. +     }
  2056.       /* we use AC_REDRAW to avoid !-commands clear the screen */
  2057.       if (parse_command(cmdbuf, AC_REDRAW, init) == START_SEQUENCE) {
  2058.           if (seq_hook_ptr) {
  2059. ***************
  2060. *** 117,123 ****
  2061. --- 123,134 ----
  2062.       /* split command string */
  2063.   
  2064.       for (argc = 0; argc < MAXARG + 2; argc++) argvec[argc] = NULL;
  2065. + strip_more:
  2066.       if ((cmd = strip_str(cmd)) == NULL || *cmd == '#') return 0;
  2067. +     if (*cmd == ':') {
  2068. +     cmd++;
  2069. +     goto strip_more;
  2070. +     }
  2071.       
  2072.       argc = 0;
  2073.       argvec[0] = cmd;
  2074. ***************
  2075. *** 163,168 ****
  2076. --- 174,187 ----
  2077.       return argvec[i];
  2078.   }
  2079.   
  2080. + static is_sequence(cmd)
  2081. + char *cmd;
  2082. + {
  2083. +     if (!split_command(cmd)) return 0;
  2084. +     if ((cmd = argv(0)) == NULL) return 0;
  2085. +     return strcmp(cmd, "sequence") == 0;
  2086. + }
  2087.       
  2088.   /*
  2089.    * parse a command (also :-commands)
  2090. ***************
  2091. *** 383,392 ****
  2092.   int ok_val;
  2093.   FILE *initf;
  2094.   {
  2095.       if (!split_command(cmd)) return ok_val;
  2096.   
  2097.       if (*ARGTAIL == '!') {
  2098. !     if (run_shell(ARGTAIL+1, ok_val == AC_PROMPT)) {
  2099.           any_key(0);
  2100.           return AC_REDRAW;
  2101.       }
  2102. --- 402,415 ----
  2103.   int ok_val;
  2104.   FILE *initf;
  2105.   {
  2106. +     extern char *m_define(), *parse_enter_macro();
  2107. +     
  2108.       if (!split_command(cmd)) return ok_val;
  2109.   
  2110.       if (*ARGTAIL == '!') {
  2111. !     if (run_shell(ARGTAIL+1, 
  2112. !               ok_val == AC_PROMPT ? 1 :
  2113. !               ok_val == AC_UNCHANGED ? -1 : 0) && ok_val != AC_UNCHANGED) {
  2114.           any_key(0);
  2115.           return AC_REDRAW;
  2116.       }
  2117. ***************
  2118. *** 458,467 ****
  2119.       if (in_init) {
  2120.           
  2121.           CASE( "load" ) {
  2122. !         if (argv(1)) load_init_file(argv(1), (FILE **)NULL);
  2123.           break;
  2124.           }
  2125.   
  2126.           CASE( "sequence" ) {
  2127.           return START_SEQUENCE;
  2128.           }
  2129. --- 481,499 ----
  2130.       if (in_init) {
  2131.           
  2132.           CASE( "load" ) {
  2133. !         if (argv(1)) load_init_file(argv(1), (FILE **)NULL, 0);
  2134.           break;
  2135.           }
  2136.   
  2137. +         CASE( "on" ) {
  2138. +         parse_on_to_end(initf);
  2139. +         break;
  2140. +         }
  2141. +         
  2142. +         CASE( "end" ) {
  2143. +         break;
  2144. +         }
  2145. +         
  2146.           CASE( "sequence" ) {
  2147.           return START_SEQUENCE;
  2148.           }
  2149. ***************
  2150. *** 810,816 ****
  2151.           if (argv(3))
  2152.           code = lookup_command(argv(3), K_ONLY_MENU);
  2153.   
  2154. !         if (code == K_MACRO)
  2155.           if (argv(4)) 
  2156.               code |= atoi(argv(4));
  2157.           else
  2158. --- 842,854 ----
  2159.           if (argv(3))
  2160.           code = lookup_command(argv(3), K_ONLY_MENU);
  2161.   
  2162. !         if (code == K_EQUAL_KEY) {
  2163. !         if (argv(4))
  2164. !             code = menu_key_map[parse_key(argv(4))];
  2165. !         else
  2166. !             goto mac_err;
  2167. !         } else
  2168. !         if (code == K_MACRO || code == K_ARTICLE_ID)
  2169.           if (argv(4)) 
  2170.               code |= atoi(argv(4));
  2171.           else
  2172. ***************
  2173. *** 826,831 ****
  2174. --- 864,875 ----
  2175.           if (argv(3))
  2176.           code = lookup_command(argv(3), K_ONLY_MORE);
  2177.           
  2178. +         if (code == K_EQUAL_KEY) {
  2179. +         if (argv(4))
  2180. +             code = menu_key_map[parse_key(argv(4))];
  2181. +         else
  2182. +             goto mac_err;
  2183. +         } else
  2184.           if (code == K_MACRO)
  2185.           if (argv(4)) 
  2186.               code |= atoi(argv(4));
  2187. ***************
  2188. *** 850,860 ****
  2189.       return;
  2190.       
  2191.    mac_err:
  2192. !     print_command("macro number missing");
  2193.       return;
  2194.   }
  2195.   
  2196.   
  2197.   display_help(subject)
  2198.   char *subject;
  2199. --- 894,955 ----
  2200.       return;
  2201.       
  2202.    mac_err:
  2203. !     print_command("last argument missing");
  2204.       return;
  2205.   }
  2206.   
  2207. ! static parse_on_to_end(f)
  2208. ! FILE *f;
  2209. ! {
  2210. !     register char *cp;
  2211. !     char buf[256];
  2212. !     
  2213. !     if (argv(1) == NULL) goto on_err;
  2214. !     SWITCH ( argv(1) ) {
  2215. !     
  2216. !     CASE( "entry" ) {
  2217. !         import char *dflt_enter_macro;
  2218. !         
  2219. !         dflt_enter_macro = parse_enter_macro(f, NL);
  2220. !         break;
  2221. !     }
  2222. ! /*    CASE( "exit" ) {
  2223. !         import char *dflt_exit_macro;
  2224. !         
  2225. !         dflt_exit_macro = parse_enter_macro(f, NL);
  2226. !         break;
  2227. !     }
  2228. ! */
  2229. !     CASE( "slow" ) {
  2230. !         import int terminal_speed, slow_speed;
  2231. !         
  2232. !         if (terminal_speed > (slow_speed / 10)) goto skip_to_end;
  2233. !         break;
  2234. !     }
  2235. !     
  2236. !     CASE( "fast" ) {
  2237. !         import int terminal_speed, slow_speed;
  2238. !         
  2239. !         if (terminal_speed <= (slow_speed / 10)) goto skip_to_end;
  2240. !         break;
  2241. !     }
  2242. !     
  2243. !     goto on_err;
  2244. !     }
  2245. !     return 0;
  2246. !     
  2247. ! skip_to_end:
  2248. !     while (fgets(buf, 256, f) != NULL) {
  2249. !     for (cp = buf; *cp && isascii(*cp) && isspace(*cp); cp++);
  2250. !     if (strncmp(cp, "end", 3) == 0) return 0;
  2251. !     }
  2252. !     init_message("end missing (on %s)", argv(1));
  2253. !     
  2254. ! on_err:
  2255. !     init_message("on `what'?");
  2256. ! }
  2257.   
  2258.   display_help(subject)
  2259.   char *subject;
  2260. *** /usr/storm/nn6.3.0/init.sample    Thu Jun  1 11:10:44 1989
  2261. --- init.sample    Fri Sep  8 12:46:44 1989
  2262. ***************
  2263. *** 8,21 ****
  2264.   # these are some of the variables you may want to set-up globally;
  2265.   # check with the manual to see if you really need them!
  2266.   
  2267.   set default-save-file +$G
  2268. ! set header-lines _FOD=S
  2269.   set mail-format
  2270.   set newsrc
  2271.   set pager /bin/less
  2272.   set printer lp -s -dnews-pr
  2273.   set retry-on-error 2
  2274. ! set save-counter .%02
  2275.   
  2276.   sequence
  2277.   
  2278. --- 8,24 ----
  2279.   # these are some of the variables you may want to set-up globally;
  2280.   # check with the manual to see if you really need them!
  2281.   
  2282. + set default-distribution local
  2283.   set default-save-file +$G
  2284. ! set header-lines _FODn=S
  2285. ! set include-art-id
  2286.   set mail-format
  2287. + set mark-overlap
  2288.   set newsrc
  2289.   set pager /bin/less
  2290.   set printer lp -s -dnews-pr
  2291.   set retry-on-error 2
  2292. ! set save-counter .%02d
  2293.   
  2294.   sequence
  2295.   
  2296. ***************
  2297. *** 49,55 ****
  2298.       # they mey include a @ in their private presentation
  2299.       # sequence to disable the '!!' operator, or they may include
  2300.       # the (few) groups they want to see.
  2301. ! !!
  2302.   
  2303.       # european groups
  2304.       # read eunet.general before eunet.followup and other eunet groups
  2305. --- 52,60 ----
  2306.       # they mey include a @ in their private presentation
  2307.       # sequence to disable the '!!' operator, or they may include
  2308.       # the (few) groups they want to see.
  2309. ! #### ONLY USE THE FOLLOWING LINE WHEN YOU UNDERSTAND WHAT ####
  2310. ! #### IT DOES AND YOU WANT THIS BEHAVIOUR ON YOUR SYSTEM   ####
  2311. ! # !!
  2312.   
  2313.       # european groups
  2314.       # read eunet.general before eunet.followup and other eunet groups
  2315. *** /usr/storm/nn6.3.2/install_aux    Wed Jun 28 20:07:52 1989
  2316. --- install_aux    Fri Sep  8 12:46:45 1989
  2317. ***************
  2318. *** 32,37 ****
  2319. --- 32,38 ----
  2320.           echo "--------------------------------------------------------"
  2321.           if [ -f $2/MASTER ]
  2322.           then
  2323. +             echo "Run 'make online' to update the online manual"
  2324.               echo "Remember to restart $DIR/nnmaster"
  2325.           else
  2326.               echo "Now run 'make initdb'"
  2327. *** /usr/storm/nn6.3.4/keymap.c    Mon Jul 10 13:36:13 1989
  2328. --- keymap.c    Fri Sep  8 12:46:45 1989
  2329. ***************
  2330. *** 63,69 ****
  2331.   /* EOT ^D */        K_NEXT_HALF_PAGE, 
  2332.   /* ENQ ^E */    K_UNBOUND, 
  2333.   /* ACK ^F */    K_UNBOUND, 
  2334. ! /* BEL ^G */    K_UNBOUND, 
  2335.   /* BS  ^H */        K_PREV_PAGE, 
  2336.   /* TAB ^I */    K_UNBOUND, 
  2337.   /* NL  ^J */        K_NEXT_LINE, 
  2338. --- 63,69 ----
  2339.   /* EOT ^D */        K_NEXT_HALF_PAGE, 
  2340.   /* ENQ ^E */    K_UNBOUND, 
  2341.   /* ACK ^F */    K_UNBOUND, 
  2342. ! /* BEL ^G */        K_INVALID, 
  2343.   /* BS  ^H */        K_PREV_PAGE, 
  2344.   /* TAB ^I */    K_UNBOUND, 
  2345.   /* NL  ^J */        K_NEXT_LINE, 
  2346. ***************
  2347. *** 263,269 ****
  2348.   /* EOT ^D */    K_UNBOUND, 
  2349.   /* ENQ ^E */    K_UNBOUND, 
  2350.   /* ACK ^F */    K_UNBOUND, 
  2351. ! /* BEL ^G */    K_UNBOUND, 
  2352.   /* BS  ^H */        K_PREV_LINE,
  2353.   /* TAB ^I */    K_UNBOUND, 
  2354.   /* NL  ^J */        K_CONTINUE,
  2355. --- 263,269 ----
  2356.   /* EOT ^D */    K_UNBOUND, 
  2357.   /* ENQ ^E */    K_UNBOUND, 
  2358.   /* ACK ^F */    K_UNBOUND, 
  2359. ! /* BEL ^G */        K_INVALID, 
  2360.   /* BS  ^H */        K_PREV_LINE,
  2361.   /* TAB ^I */    K_UNBOUND, 
  2362.   /* NL  ^J */        K_CONTINUE,
  2363. ***************
  2364. *** 411,416 ****
  2365. --- 411,418 ----
  2366.       
  2367.       "advance-article",        K_FORW_ARTICLE,        K_ONLY_MORE,
  2368.       "advance-group",        K_ADVANCE_GROUP,    0,
  2369. +     "article",            K_ARTICLE_ID,        K_ONLY_MENU,
  2370. +     "as",            K_EQUAL_KEY,        0,
  2371.   
  2372.       "back-article",        K_BACK_ARTICLE,        K_ONLY_MORE,
  2373.       "back-group",        K_BACK_GROUP,        0,
  2374. ***************
  2375. *** 496,502 ****
  2376.   static int name_map_size;
  2377.   static int max_cmd_name_length = 14;    /* recalculate if table is changed */
  2378.   
  2379. ! export char global_key_map[KEY_MAP_SIZE];
  2380.   
  2381.   
  2382.   init_key_map()
  2383. --- 498,504 ----
  2384.   static int name_map_size;
  2385.   static int max_cmd_name_length = 14;    /* recalculate if table is changed */
  2386.   
  2387. ! export unsigned char global_key_map[KEY_MAP_SIZE];
  2388.   
  2389.   
  2390.   init_key_map()
  2391. ***************
  2392. *** 587,593 ****
  2393.           index = strncmp(cmd->cmd_name, head, len);
  2394.       if (index < 0) continue;
  2395.       if (index > 0) break;
  2396. !     if (cmd->cmd_code == K_MACRO)
  2397.           sprintf(tail, "%s ", cmd->cmd_name + len);
  2398.       else
  2399.           strcpy(tail, cmd->cmd_name + len);
  2400. --- 589,597 ----
  2401.           index = strncmp(cmd->cmd_name, head, len);
  2402.       if (index < 0) continue;
  2403.       if (index > 0) break;
  2404. !     if (cmd->cmd_code == K_MACRO || 
  2405. !         cmd->cmd_code == K_ARTICLE_ID ||
  2406. !         cmd->cmd_code == K_EQUAL_KEY)
  2407.           sprintf(tail, "%s ", cmd->cmd_name + len);
  2408.       else
  2409.           strcpy(tail, cmd->cmd_name + len);
  2410. ***************
  2411. *** 637,643 ****
  2412.       if (str[1] == '?') 
  2413.           return 0177;
  2414.       else
  2415. !         return CTRL(str[1]);
  2416.       
  2417.       if (isdigit(str[0])) {
  2418.       if (str[0] == '0')
  2419. --- 641,647 ----
  2420.       if (str[1] == '?') 
  2421.           return 0177;
  2422.       else
  2423. !         return CONTROL_(str[1]);
  2424.       
  2425.       if (isdigit(str[0])) {
  2426.       if (str[0] == '0')
  2427. *** /usr/storm/nn6.3.4/keymap.h    Mon Jul 10 13:36:14 1989
  2428. --- keymap.h    Fri Sep  8 12:46:45 1989
  2429. ***************
  2430. *** 94,99 ****
  2431. --- 94,101 ----
  2432.       
  2433.   #define K_PREVIEW        0x004f /* preview article         */
  2434.   
  2435. + #define    K_EQUAL_KEY        0x0070 /* map command special symbol    */
  2436.   #define    K_MACRO            0x0100 /* call macro            */
  2437.   #define    K_ARTICLE_ID        0x0200 /* article id in lower part    */
  2438.   
  2439. ***************
  2440. *** 115,118 ****
  2441.   extern int menu_key_map[];
  2442.   extern int more_key_map[];
  2443.   
  2444. ! extern char global_key_map[];
  2445. --- 117,120 ----
  2446.   extern int menu_key_map[];
  2447.   extern int more_key_map[];
  2448.   
  2449. ! extern unsigned char global_key_map[];
  2450. *** /usr/storm/nn6.3.0/log_entry.c    Thu Jun  1 11:10:45 1989
  2451. --- log_entry.c    Fri Sep  8 12:46:45 1989
  2452. ***************
  2453. *** 29,31 ****
  2454. --- 29,34 ----
  2455.       nn_exit(1);
  2456.   }
  2457.   
  2458. + suspend_nn()
  2459. + {
  2460. + }
  2461. *** /usr/storm/nn6.3.4/m-i80286.h    Mon Jul 10 14:47:39 1989
  2462. --- m-i80286.h    Fri Sep  8 12:46:46 1989
  2463. ***************
  2464. *** 12,17 ****
  2465. --- 12,18 ----
  2466.   typedef long        int32;        /* -100,000 .. 100,000 */
  2467.   typedef unsigned long    uint32;        /*       0 ..  2^31-1 */
  2468.   
  2469. + #define I286_BUG
  2470.   
  2471.   /*
  2472.    *     Define NO_VARARGS if the varargs feature is not available
  2473. *** /usr/storm/nn6.3.4/macro.c    Mon Jul 10 13:36:16 1989
  2474. --- macro.c    Fri Sep  8 12:46:46 1989
  2475. ***************
  2476. *** 5,10 ****
  2477. --- 5,11 ----
  2478.   export int in_menu_mode = 0;
  2479.   export int get_from_macro = 0;
  2480.   export int macro_debug = 0;
  2481. + export char *dflt_enter_macro = NULL;
  2482.   
  2483.   #define M_DUMMY        0    /* do nothing (end of branch)     */
  2484.   
  2485. ***************
  2486. *** 18,23 ****
  2487. --- 19,25 ----
  2488.   #define M_NO        6    /* answer no to confirmation and break */
  2489.                   /* -- if neither are present, take input */
  2490.   
  2491. + #define M_PUTS        7    /* puts "..."             */
  2492.   #define M_PROMPT    8    /* prompt(...)              */
  2493.   #define M_ECHO        9    /* msg(...)             */
  2494.   
  2495. ***************
  2496. *** 31,37 ****
  2497. --- 33,41 ----
  2498.   #define M_BREAK        17    /* exit from macroes         */
  2499.   #define    M_RETURN    18    /* return from this macro     */
  2500.   
  2501. + #define    M_SET_COMMAND    19    /* set/unset command         */
  2502.   
  2503.   struct macro {
  2504.       int            m_type;        /* entry type */
  2505.       union {
  2506. ***************
  2507. *** 46,62 ****
  2508.   #define m_string    m_value.mu_string
  2509.   #define m_branch    m_value.mu_branch
  2510.   
  2511. ! #define NMACRO 32        /* max number of macros */
  2512.   #define MSTACK 5        /* max nesting level */
  2513.   
  2514. ! static struct macro *macro[NMACRO];     /* macro table */
  2515.   
  2516.   static struct macro *mstack[MSTACK];    /* macro stack */
  2517. ! static int cstack[MSTACK];
  2518.   static int m_level = 0;
  2519.   
  2520.   static struct macro *m = NULL;        /* current macro */
  2521.   static int no_advance = 0;
  2522.   
  2523.   static int cur_m;
  2524.   
  2525. --- 50,67 ----
  2526.   #define m_string    m_value.mu_string
  2527.   #define m_branch    m_value.mu_branch
  2528.   
  2529. ! #define NMACRO 101        /* max number of macros */
  2530.   #define MSTACK 5        /* max nesting level */
  2531.   
  2532. ! static struct macro *macro[NMACRO + 1];     /* macro table */
  2533.   
  2534.   static struct macro *mstack[MSTACK];    /* macro stack */
  2535. ! static int cstack[MSTACK + 1];
  2536.   static int m_level = 0;
  2537.   
  2538.   static struct macro *m = NULL;        /* current macro */
  2539.   static int no_advance = 0;
  2540. + static int changed_prompt = 0;
  2541.   
  2542.   static int cur_m;
  2543.   
  2544. ***************
  2545. *** 66,72 ****
  2546.   {
  2547.       int n;
  2548.       
  2549. !     for (n = 0; n < NMACRO; n++)
  2550.       macro[n] = NULL;
  2551.   }
  2552.   
  2553. --- 71,77 ----
  2554.   {
  2555.       int n;
  2556.       
  2557. !     for (n = 0; n <= NMACRO; n++)
  2558.       macro[n] = NULL;
  2559.   }
  2560.   
  2561. ***************
  2562. *** 98,105 ****
  2563.    *        end
  2564.    */
  2565.   
  2566.   
  2567. ! m_define(id, f)
  2568.   char *id;
  2569.   FILE *f;
  2570.   {
  2571. --- 103,111 ----
  2572.    *        end
  2573.    */
  2574.   
  2575. + static int initial_set_commands;
  2576.   
  2577. ! char *m_define(id, f)
  2578.   char *id;
  2579.   FILE *f;
  2580.   {
  2581. ***************
  2582. *** 107,115 ****
  2583.   
  2584.       if (id) {
  2585.       cur_m = atoi(id);
  2586. !     if (cur_m < 0 || cur_m >= NMACRO) {
  2587.           m_error("macro number out of range\n", id);
  2588. !         return 0;
  2589.       }
  2590.       } else {
  2591.       for (cur_m = 0; cur_m < NMACRO; cur_m++)
  2592. --- 113,123 ----
  2593.   
  2594.       if (id) {
  2595.       cur_m = atoi(id);
  2596. !     if (cur_m < 0)
  2597. !         cur_m = NMACRO;
  2598. !     else if (cur_m >= NMACRO) {
  2599.           m_error("macro number out of range\n", id);
  2600. !         return (char *)0;
  2601.       }
  2602.       } else {
  2603.       for (cur_m = 0; cur_m < NMACRO; cur_m++)
  2604. ***************
  2605. *** 116,122 ****
  2606.           if (macro[cur_m] == NULL) break;
  2607.       if (cur_m == NMACRO) {
  2608.           init_message("No unused macro numbers");
  2609. !         return 0;
  2610.       }
  2611.       }
  2612.       
  2613. --- 124,130 ----
  2614.           if (macro[cur_m] == NULL) break;
  2615.       if (cur_m == NMACRO) {
  2616.           init_message("No unused macro numbers");
  2617. !         return (char *)0;
  2618.       }
  2619.       }
  2620.       
  2621. ***************
  2622. *** 129,139 ****
  2623.       
  2624.       m = NULL;
  2625.       skip = 0;
  2626.       while (fgets(line, 256, f)) {
  2627.       for (lp = line; *lp && isspace(*lp); lp++);
  2628.       if (*lp == NUL) continue;
  2629. !     if (strncmp(lp, "end", 3) == 0) goto out;
  2630.       if (!skip && parse_line(lp)) {
  2631.           macro[cur_m] = NULL;
  2632.           skip++;
  2633. --- 137,148 ----
  2634.       
  2635.       m = NULL;
  2636.       skip = 0;
  2637. !     initial_set_commands = (cur_m == NMACRO);
  2638. !     
  2639.       while (fgets(line, 256, f)) {
  2640.       for (lp = line; *lp && isspace(*lp); lp++);
  2641.       if (*lp == NUL) continue;
  2642. !     if (*lp == ')' || strncmp(lp, "end", 3) == 0) goto out;
  2643.       if (!skip && parse_line(lp)) {
  2644.           macro[cur_m] = NULL;
  2645.           skip++;
  2646. ***************
  2647. *** 146,152 ****
  2648.    out:
  2649.       if (f == stdin) raw();
  2650.       m = NULL;
  2651. !     return 1;
  2652.   }
  2653.   
  2654.   static parse_line(lp)
  2655. --- 155,203 ----
  2656.    out:
  2657.       if (f == stdin) raw();
  2658.       m = NULL;
  2659. !     return (char *)macro[cur_m];
  2660. ! }
  2661. ! char *m_get_macro(id)
  2662. ! char *id;
  2663. ! {
  2664. !     if (id) {
  2665. !     cur_m = atoi(id);
  2666. !     if (cur_m < 0 || cur_m >= NMACRO) {
  2667. !         m_error("macro number out of range\n", id);
  2668. !         return (char *)0;
  2669. !     }
  2670. !     } 
  2671. !     return (char *)macro[cur_m];
  2672. ! }
  2673. ! char *parse_enter_macro(f, c)
  2674. ! FILE *f;
  2675. ! register int c;
  2676. ! {
  2677. !     register char *gp;
  2678. !     char other[FILENAME];
  2679. !     group_header *gh;
  2680. !     static char *last_defined = NULL;
  2681. !     
  2682. !     while (c != EOF && c != NL && (!isascii(c) || isspace(c))) c = getc(f);
  2683. !     if (c == ')') return last_defined;
  2684. !     
  2685. !     if (c == EOF) return (char *)NULL;
  2686. !     
  2687. !     if (c == NL) return last_defined = m_define("-1", f);
  2688. !     gp = other; 
  2689. !     do {
  2690. !     *gp++ = c;
  2691. !     c = getc(f);
  2692. !     } while (c != EOF && c != ')' && isascii(c) && !isspace(c));
  2693. !     *gp = NUL;
  2694. !     if (gh = lookup(other)) return gh->enter_macro;
  2695. !     
  2696. !     return m_get_macro(other);
  2697.   }
  2698.   
  2699.   static parse_line(lp)
  2700. ***************
  2701. *** 159,170 ****
  2702.       if (*lp == '#') break;
  2703.       
  2704.       if (*lp == ':') {
  2705.           m_new(M_COMMAND);
  2706.           m->m_int = GETC_COMMAND | K_EXTENDED_CMD;
  2707.           m_new(M_STRING);
  2708. !         m->m_string = copy_str(lp + 1);
  2709.           break;
  2710.       }
  2711.   
  2712.       if (*lp == '?') {
  2713.           m_new(M_IS_MENU);
  2714. --- 210,231 ----
  2715.       if (*lp == '#') break;
  2716.       
  2717.       if (*lp == ':') {
  2718. +         lp++;
  2719. +         if (initial_set_commands) {
  2720. +         if (!strncmp(lp, "set", 3) || !strncmp(lp, "unset", 5)) {
  2721. +             m_new(M_SET_COMMAND);
  2722. +             m->m_string = copy_str(lp);
  2723. +             break;
  2724. +         }
  2725. +         initial_set_commands = 0;
  2726. +         }
  2727.           m_new(M_COMMAND);
  2728.           m->m_int = GETC_COMMAND | K_EXTENDED_CMD;
  2729.           m_new(M_STRING);
  2730. !         m->m_string = copy_str(lp);
  2731.           break;
  2732.       }
  2733. +     initial_set_commands = 0;
  2734.   
  2735.       if (*lp == '?') {
  2736.           m_new(M_IS_MENU);
  2737. ***************
  2738. *** 217,223 ****
  2739.       }
  2740.   
  2741.       if (*w == '"') {
  2742. !     if (m == NULL || (m->m_type != M_PROMPT && m->m_type != M_ECHO))
  2743.           m_new(M_STRING);
  2744.       m->m_string = copy_str(w + 1);
  2745.       goto ok;
  2746. --- 278,284 ----
  2747.       }
  2748.   
  2749.       if (*w == '"') {
  2750. !     if (m == NULL || (m->m_type != M_PROMPT && m->m_type != M_ECHO && m->m_type != M_PUTS))
  2751.           m_new(M_STRING);
  2752.       m->m_string = copy_str(w + 1);
  2753.       goto ok;
  2754. ***************
  2755. *** 282,287 ****
  2756. --- 343,353 ----
  2757.       m->m_string = "ups";
  2758.       goto ok;
  2759.       }
  2760. +     if (strcmp(w, "puts") == 0) {
  2761. +     m_new(M_PUTS);
  2762. +     m->m_string = "";
  2763. +     goto ok;
  2764. +     }
  2765.       if (strcmp(w, "input") == 0) {
  2766.       m_new(M_INPUT);
  2767.       goto ok;
  2768. ***************
  2769. *** 317,343 ****
  2770.   m_invoke(n)
  2771.   int n;
  2772.   {
  2773. !     if (n < 0 || n > NMACRO || macro[n] == NULL) {
  2774.       msg("undefined macro %d", n);
  2775.       return;
  2776.       }
  2777.   
  2778. !     if (m == NULL)
  2779.       no_advance = 0;
  2780.       else {
  2781. !     if (m_level == MSTACK) {
  2782.           msg("Macro stack overflow");
  2783. !         m = NULL;
  2784. !         m_level = 0;
  2785.           return;
  2786.       }
  2787.       mstack[m_level] = m;
  2788.       cstack[m_level] = cur_m;
  2789. -     m_level++;
  2790.       }
  2791.   
  2792.       cur_m = n;
  2793.       m = macro[cur_m];
  2794.   }
  2795.   
  2796.   m_startinput()
  2797. --- 383,421 ----
  2798.   m_invoke(n)
  2799.   int n;
  2800.   {
  2801. !     if (n < 0) {
  2802. !     n = NMACRO;
  2803. !     if ((macro[n] = (struct macro *)(current_group->enter_macro)) == NULL)
  2804. !         if ((macro[n] = (struct macro *)dflt_enter_macro) == NULL)
  2805. !         return;
  2806. !     } else 
  2807. !     if (n >= NMACRO || macro[n] == NULL) {
  2808.       msg("undefined macro %d", n);
  2809.       return;
  2810.       }
  2811.   
  2812. !     if (m_level == 0)
  2813.       no_advance = 0;
  2814.       else {
  2815. !     if (m_level > MSTACK) {
  2816.           msg("Macro stack overflow");
  2817. !         m_break();
  2818.           return;
  2819.       }
  2820.       mstack[m_level] = m;
  2821.       cstack[m_level] = cur_m;
  2822.       }
  2823. +     m_level++;
  2824.   
  2825.       cur_m = n;
  2826.       m = macro[cur_m];
  2827. +     while (m && m->m_type == M_SET_COMMAND) {
  2828. +     char buffer[128];
  2829. +     strcpy(buffer, m->m_string); 
  2830. +     if (macro_debug) { msg(":%s", buffer); user_delay(1); }
  2831. +     parse_command(buffer, 0, (FILE *)NULL);
  2832. +     m = m->m_next;
  2833. +     }
  2834.   }
  2835.   
  2836.   m_startinput()
  2837. ***************
  2838. *** 366,372 ****
  2839.       struct macro *m1;
  2840.   
  2841.       for (;;) {
  2842. !     while (m == NULL && m_level > 0) {
  2843.           m_level--;
  2844.           m = mstack[m_level];
  2845.           cur_m = cstack[m_level];
  2846. --- 444,450 ----
  2847.       struct macro *m1;
  2848.   
  2849.       for (;;) {
  2850. !     while (m == NULL && m_level > 1) {
  2851.           m_level--;
  2852.           m = mstack[m_level];
  2853.           cur_m = cstack[m_level];
  2854. ***************
  2855. *** 373,378 ****
  2856. --- 451,457 ----
  2857.       }
  2858.       if (m == NULL) {
  2859.           if (macro_debug) msg("end");
  2860. +         m_break();
  2861.           return NULL;
  2862.       }
  2863.       
  2864. ***************
  2865. *** 386,391 ****
  2866. --- 465,472 ----
  2867.   
  2868.       switch (m->m_type) {
  2869.        case M_COMMAND:
  2870. +         if (m->m_int == (GETC_COMMAND | K_REDRAW))
  2871. +         changed_prompt = 0;
  2872.        case M_KEY:
  2873.           if (who == 1) goto out;
  2874.           goto err;
  2875. ***************
  2876. *** 403,414 ****
  2877. --- 484,506 ----
  2878.        case M_DUMMY:
  2879.           break;
  2880.   
  2881. +      case M_PUTS:
  2882. +         fputs(m->m_string, stdout); fl;
  2883. +         break;
  2884. +         
  2885.        case M_PROMPT:
  2886. +         if (m->m_string[0] == NUL) {
  2887. +         changed_prompt = 0;
  2888. +         break;
  2889. +         }
  2890. +         if (!changed_prompt) prompt(P_SAVE);
  2891. +         changed_prompt = 1;
  2892.           prompt("\1%s\1 ", m->m_string);
  2893.           break;
  2894.   
  2895.        case M_ECHO:
  2896.           msg(m->m_string);
  2897. +         restore_xy();
  2898.           break;
  2899.   
  2900.        case M_IS_MENU:
  2901. ***************
  2902. *** 424,433 ****
  2903.           if ((current_group->group_flag & G_FOLDER) == 0) m = m->m_branch;
  2904.           break;
  2905.        case M_CONFIRM:
  2906. !         if (!yes(0)) m = m->m_branch;
  2907.           break;
  2908.        case M_REJECT:
  2909. !         if (yes(0)) m = m->m_branch;
  2910.           break;
  2911.   
  2912.        case M_VARTEST:
  2913. --- 516,525 ----
  2914.           if ((current_group->group_flag & G_FOLDER) == 0) m = m->m_branch;
  2915.           break;
  2916.        case M_CONFIRM:
  2917. !         if (yes(0) == 0) m = m->m_branch;
  2918.           break;
  2919.        case M_REJECT:
  2920. !         if (yes(0) == 1) m = m->m_branch;
  2921.           break;
  2922.   
  2923.        case M_VARTEST:
  2924. ***************
  2925. *** 451,457 ****
  2926.           goto term;
  2927.       }
  2928.   
  2929. !     m = m->m_next;
  2930.       }
  2931.   
  2932.    out:
  2933. --- 543,549 ----
  2934.           goto term;
  2935.       }
  2936.   
  2937. !     if (m) m = m->m_next;
  2938.       }
  2939.   
  2940.    out:
  2941. ***************
  2942. *** 464,481 ****
  2943.       msg("Error in macro %d", cur_m);
  2944.    err1:
  2945.       user_delay(1);
  2946. !     m = NULL;
  2947. !     m_level = 0;
  2948.       return MERROR;
  2949.   
  2950.    term:
  2951. !     m = NULL;
  2952. !     m_level = 0;
  2953.       return NULL;
  2954.   }
  2955.   
  2956.   m_break()
  2957.   {
  2958.       m = NULL;
  2959.       m_level = 0;
  2960.   }
  2961. --- 556,579 ----
  2962.       msg("Error in macro %d", cur_m);
  2963.    err1:
  2964.       user_delay(1);
  2965. !     m_break();
  2966.       return MERROR;
  2967.   
  2968.    term:
  2969. !     m_break();
  2970.       return NULL;
  2971.   }
  2972.   
  2973. + m_break_entry()
  2974. + {
  2975. +     if (current_group->enter_macro || dflt_enter_macro)
  2976. +     m = NULL;
  2977. + }
  2978.   m_break()
  2979.   {
  2980. +     if (changed_prompt) prompt(P_RESTORE);
  2981. +     changed_prompt = 0;
  2982.       m = NULL;
  2983.       m_level = 0;
  2984.   }
  2985. ***************
  2986. *** 573,579 ****
  2987.       struct macro *m1;
  2988.       
  2989.       get_from_macro = 0;
  2990. !     if (m && (m1 = m_call(1))) {
  2991.       if (m1 == MERROR) return 2;
  2992.       if (m1->m_type == M_INPUT) return 0;
  2993.       *cp = m1->m_int;
  2994. --- 671,677 ----
  2995.       struct macro *m1;
  2996.       
  2997.       get_from_macro = 0;
  2998. !     if (m_level && (m1 = m_call(1))) {
  2999.       if (m1 == MERROR) return 2;
  3000.       if (m1->m_type == M_INPUT) return 0;
  3001.       *cp = m1->m_int;
  3002. ***************
  3003. *** 593,599 ****
  3004.       struct macro *m1;
  3005.   
  3006.       get_from_macro = 0;
  3007. !     if (m && (m1 = m_call(2))) {
  3008.       if (m1 == MERROR) return 2;
  3009.       if (m1->m_type == M_INPUT) return 0;
  3010.       strcpy(s, m1->m_string);
  3011. --- 691,697 ----
  3012.       struct macro *m1;
  3013.   
  3014.       get_from_macro = 0;
  3015. !     if (m_level && (m1 = m_call(2))) {
  3016.       if (m1 == MERROR) return 2;
  3017.       if (m1->m_type == M_INPUT) return 0;
  3018.       strcpy(s, m1->m_string);
  3019. ***************
  3020. *** 611,617 ****
  3021.   {
  3022.       struct macro *m1;
  3023.   
  3024. !     if (m) {
  3025.       if (m1 = m_call(3))
  3026.           if (m1->m_type == M_NO)
  3027.           return 1;
  3028. --- 709,718 ----
  3029.   {
  3030.       struct macro *m1;
  3031.   
  3032. !     if (m)
  3033. !     if (m->m_type == M_CONFIRM || m->m_type == M_REJECT) return 3;
  3034. !     
  3035. !     if (m_level) {
  3036.       if (m1 = m_call(3))
  3037.           if (m1->m_type == M_NO)
  3038.           return 1;
  3039. *** /usr/storm/nn6.3.4/master.c    Mon Jul 10 13:36:19 1989
  3040. --- master.c    Fri Sep  8 12:46:47 1989
  3041. ***************
  3042. *** 177,183 ****
  3043.           nntp_close_server();
  3044.           current_group = NULL; /* for init_group */
  3045.           log_entry('N', "Can't access active file --- %s",
  3046. !               repeat_delay ? "sleeping" : "termating");
  3047.           if (repeat_delay == 0)
  3048.           nn_exit(1);
  3049.           sleep(repeat_delay);
  3050. --- 177,183 ----
  3051.           nntp_close_server();
  3052.           current_group = NULL; /* for init_group */
  3053.           log_entry('N', "Can't access active file --- %s",
  3054. !               repeat_delay ? "sleeping" : "terminating");
  3055.           if (repeat_delay == 0)
  3056.           nn_exit(1);
  3057.           sleep(repeat_delay);
  3058. ***************
  3059. *** 751,756 ****
  3060. --- 751,760 ----
  3061.       sys_error("Dummy routine called by master: %s", name);
  3062.   }
  3063.   
  3064. + #ifdef HAVE_JOBCONTROL
  3065. + suspend_nn()
  3066. + {}
  3067. + #endif
  3068.   
  3069.   #ifdef NNTP /* XXX */
  3070.   msg() {}
  3071. *** /usr/storm/nn6.3.4/menu.c    Mon Jul 10 13:36:20 1989
  3072. --- menu.c    Fri Sep  8 12:46:47 1989
  3073. ***************
  3074. *** 16,21 ****
  3075. --- 16,24 ----
  3076.   export int  novice       = 1; /* novice mode -- use extended prompts */
  3077.   export int  long_menu       = 0; /* don't put empty lines around menu lines */
  3078.   export int  delay_redraw   = 0; /* prompt again if :-command clears screen */
  3079. + export int  slow_mode       = 0;    /* mark selected articles with *s */
  3080. + export int  re_layout      = 0; /* Re: format presentation on menus */
  3081. + export int  collapse_subject = 25; /* collapse long subjects at position */
  3082.   
  3083.   export char *delayed_msg = NULL;    /* give to msg() after redraw */
  3084.   export long dl_msg_arg = 0;        /* optional arg to delayed_msg */
  3085. ***************
  3086. *** 23,28 ****
  3087. --- 26,35 ----
  3088.   import also_read_articles;
  3089.   import merged_menu;
  3090.   
  3091. + #ifdef NNTP
  3092. + import int use_nntp;            /* is nntp in use? */
  3093. + #endif
  3094.   extern group_completion();
  3095.   
  3096.   static regexp *regular_expr = NULL;
  3097. ***************
  3098. *** 63,69 ****
  3099.       if (how == curhow) return;
  3100.   
  3101.       lno = firstl + cura;
  3102. !     must_print = STANDOUT;
  3103.   
  3104.    toggle:
  3105.   
  3106. --- 70,76 ----
  3107.       if (how == curhow) return;
  3108.   
  3109.       lno = firstl + cura;
  3110. !     must_print = !slow_mode && STANDOUT;
  3111.   
  3112.    toggle:
  3113.   
  3114. ***************
  3115. *** 137,143 ****
  3116.   
  3117.       if (must_print) {
  3118.   
  3119. !     if (fmt_linenum > 4) fmt_linenum = 1;
  3120.       
  3121.       if (ah->flag & (A_CANCEL | A_LEAVE | A_LEAVE_NEXT | A_READ)) {
  3122.           gotoxy(1, lno);
  3123. --- 144,150 ----
  3124.   
  3125.       if (must_print) {
  3126.   
  3127. !     if (fmt_linenum > 5) fmt_linenum = 1;
  3128.       
  3129.       if (ah->flag & (A_CANCEL | A_LEAVE | A_LEAVE_NEXT | A_READ)) {
  3130.           gotoxy(1, lno);
  3131. ***************
  3132. *** 148,161 ****
  3133.               '='
  3134.               );
  3135.       } else
  3136. !     if (how == ON) {
  3137.           if (so_gotoxy(1, lno, 1) == 0) putchar('*');
  3138.       } else {
  3139.           gotoxy(1, lno);
  3140. !         putchar(' ');
  3141.       }
  3142.   
  3143. -     if (fmt_linenum >   1) lnum = 0; else
  3144.       if (ah->lines <    10) lnum = 1; else
  3145.       if (ah->lines <   100) lnum = 2; else
  3146.       if (ah->lines <  1000) lnum = 3; else
  3147. --- 155,167 ----
  3148.               '='
  3149.               );
  3150.       } else
  3151. !     if (how == ON && !slow_mode) {
  3152.           if (so_gotoxy(1, lno, 1) == 0) putchar('*');
  3153.       } else {
  3154.           gotoxy(1, lno);
  3155. !         putchar(how == ON ? '*' : ' ');
  3156.       }
  3157.   
  3158.       if (ah->lines <    10) lnum = 1; else
  3159.       if (ah->lines <   100) lnum = 2; else
  3160.       if (ah->lines <  1000) lnum = 3; else
  3161. ***************
  3162. *** 169,180 ****
  3163.           lsubj -= NAME_LENGTH + 1 + 2 + lnum;  /* name. .subj. +.lines */
  3164.           so_printf("%-*s ", NAME_LENGTH, ah->sender);
  3165.           break;
  3166. !         
  3167.        case 1:
  3168. !         lsubj -= NAME_LENGTH + 4; 
  3169.           /* name.lines.  .subj (name may be shortened) */
  3170.           lname = NAME_LENGTH + 2 - lnum;
  3171. -         lsubj -= 4;    /* 2 columns for the number + 2 spaces */
  3172.           so_printf("%-*.*s ", lname, lname, ah->sender);
  3173.           so_printf(ah->lines >= 0 ? "%d  " : "?  ", ah->lines);
  3174.           break;
  3175. --- 175,194 ----
  3176.           lsubj -= NAME_LENGTH + 1 + 2 + lnum;  /* name. .subj. +.lines */
  3177.           so_printf("%-*s ", NAME_LENGTH, ah->sender);
  3178.           break;
  3179. !      case 5:
  3180. !         if (ah->subj_length > (lsubj - NAME_LENGTH - 5))
  3181. !         if (fmt_rptsubj || lno == firstl || (ah->flag & A_SAME) == 0) {
  3182. !             so_printf("  ");
  3183. !             lsubj -= 2;
  3184. !             break;
  3185. !         }
  3186. !         /* else use layout 1, so fall thru */
  3187.        case 1:
  3188. !         lsubj -= NAME_LENGTH + 5;
  3189.           /* name.lines.  .subj (name may be shortened) */
  3190.           lname = NAME_LENGTH + 2 - lnum;
  3191.           so_printf("%-*.*s ", lname, lname, ah->sender);
  3192.           so_printf(ah->lines >= 0 ? "%d  " : "?  ", ah->lines);
  3193.           break;
  3194. ***************
  3195. *** 194,206 ****
  3196.       }
  3197.   
  3198.       if (!fmt_rptsubj && lno > firstl && ah->flag & A_SAME) {
  3199. !         if (ah->replies == 0)
  3200.           so_printf("-");
  3201. -         else
  3202. -         prt_replies(ah->replies);
  3203.       } else {
  3204.           lsubj -= prt_replies(ah->replies);
  3205. !         so_printf("%-.*s", lsubj, ah->subject);
  3206.       }    
  3207.   
  3208.       if (fmt_linenum == 0)
  3209. --- 208,228 ----
  3210.       }
  3211.   
  3212.       if (!fmt_rptsubj && lno > firstl && ah->flag & A_SAME) {
  3213. !         if (ah->replies == 0 || prt_replies(ah->replies) == 0)
  3214.           so_printf("-");
  3215.       } else {
  3216.           lsubj -= prt_replies(ah->replies);
  3217. !         if (lsubj >= ah->subj_length)
  3218. !         so_printf("%s", ah->subject);
  3219. !         else
  3220. !         if (collapse_subject < 0)
  3221. !         so_printf("%-.*s", lsubj, ah->subject);
  3222. !         else {
  3223. !         if (collapse_subject > 0)
  3224. !             so_printf("%-.*s", collapse_subject, ah->subject);
  3225. !         lsubj -= 2 + collapse_subject;
  3226. !         so_printf("<>%s", ah->subject + ah->subj_length - lsubj);
  3227. !         }        
  3228.       }    
  3229.   
  3230.       if (fmt_linenum == 0)
  3231. ***************
  3232. *** 218,224 ****
  3233. --- 240,263 ----
  3234.   
  3235.   static prt_replies(level)
  3236.   {
  3237. +     int re;
  3238. +     
  3239.       if (level == 0) return 0;
  3240. +     re = level & 0x80;
  3241. +     level &= 0x7f;
  3242. +     switch (re_layout) {
  3243. +      case 1:
  3244. +     if (!re) return 0;
  3245. +     so_printf(">");
  3246. +     return 1;
  3247. +      case 2:
  3248. +     so_printf("%d>", level);
  3249. +     return level < 10 ? 2 : 3;
  3250. +      case 3:
  3251. +     so_printf("Re: ");
  3252. +     return 4;
  3253. +     }
  3254.       
  3255.       if (level < 10) {
  3256.       so_printf("%-.*s", level, ">>>>>>>>>");
  3257. ***************
  3258. *** 305,311 ****
  3259.       static        menu_level = 0;
  3260.       char        purpose[80], pr_fmt[60];
  3261.       extern int         enable_stop, file_completion();
  3262. !     extern int        alt_cmd_key, in_menu_mode, slow_mode, any_message;
  3263.       article_number    elim_list[3];
  3264.       
  3265.   #define    menu_return(cmd) \
  3266. --- 344,350 ----
  3267.       static        menu_level = 0;
  3268.       char        purpose[80], pr_fmt[60];
  3269.       extern int         enable_stop, file_completion();
  3270. !     extern int        alt_cmd_key, in_menu_mode, any_message;
  3271.       article_number    elim_list[3];
  3272.       
  3273.   #define    menu_return(cmd) \
  3274. ***************
  3275. *** 453,458 ****
  3276. --- 492,498 ----
  3277.        if (numa >= 0) {
  3278.        gotoxy(0, firstl + cura); 
  3279.        fl; /* place cursor at current article id */
  3280. +      save_xy();
  3281.        }
  3282.   
  3283.        last_k_cmd = cur_k_cmd;
  3284. ***************
  3285. *** 466,474 ****
  3286. --- 506,516 ----
  3287.         case K_UNBOUND:
  3288.        ding();
  3289.        flush_input();
  3290. +       case K_INVALID:
  3291.        goto same_prompt;
  3292.   
  3293.         case K_REDRAW:
  3294. +      next_cura = cura;
  3295.        goto redraw;
  3296.   
  3297.         case K_LAST_MESSAGE:
  3298. ***************
  3299. *** 492,497 ****
  3300. --- 534,542 ----
  3301.         case K_EXTENDED_CMD:
  3302.        switch (alt_command()) {
  3303.   
  3304. +       case AC_UNCHANGED:
  3305. +          goto same_prompt;
  3306. +          
  3307.         case AC_QUIT:
  3308.            menu_return( ME_QUIT );
  3309.   
  3310. ***************
  3311. *** 543,548 ****
  3312. --- 588,596 ----
  3313.   
  3314.        m_startinput();
  3315.   
  3316. +      if (novice) 
  3317. +          msg(" * selected articles on this page, + all selected articles");
  3318. +      
  3319.        while (!save_selected && !did_unshar) {
  3320.            prompt("\1%s\1 %.*s Article (* +): ",
  3321.               savemode, Columns - 25, fname);
  3322. ***************
  3323. *** 636,643 ****
  3324.        }    
  3325.        goto Prompt;
  3326.   
  3327. -       case K_REPLY:
  3328.         case K_FOLLOW_UP:
  3329.        if (numa < 0) goto nextmenu;
  3330.   
  3331.        prompt(k_cmd == K_REPLY ? 
  3332. --- 684,694 ----
  3333.        }    
  3334.        goto Prompt;
  3335.   
  3336.         case K_FOLLOW_UP:
  3337. + #ifdef NNTP_POST
  3338. +      if (use_nntp && nntp_no_post()) goto same_prompt;
  3339. + #endif
  3340. +       case K_REPLY:
  3341.        if (numa < 0) goto nextmenu;
  3342.   
  3343.        prompt(k_cmd == K_REPLY ? 
  3344. ***************
  3345. *** 651,656 ****
  3346. --- 702,712 ----
  3347.        goto Prompt;
  3348.   
  3349.         case K_POST:
  3350. + #ifdef NNTP_POST
  3351. +      if (use_nntp && nntp_no_post())
  3352. +          goto same_prompt;
  3353. + #endif
  3354.        if (post_menu()) goto redraw;
  3355.        goto Prompt;
  3356.   
  3357. ***************
  3358. *** 699,705 ****
  3359.        goto Prompt;
  3360.   
  3361.         case K_GROUP_OVERVIEW:
  3362. !      group_overview(0);
  3363.        goto redraw;
  3364.   
  3365.         case K_KILL_HANDLING:
  3366. --- 755,761 ----
  3367.        goto Prompt;
  3368.   
  3369.         case K_GROUP_OVERVIEW:
  3370. !      group_overview(-1);
  3371.        goto redraw;
  3372.   
  3373.         case K_KILL_HANDLING:
  3374. ***************
  3375. *** 1339,1347 ****
  3376.       extern char erase_key;
  3377.       extern int get_from_macro;
  3378.       extern int alt_completion();
  3379. !     
  3380. !     prompt(":");
  3381. !     ok_val = AC_PROMPT;
  3382.       
  3383.    again:
  3384.       
  3385. --- 1395,1407 ----
  3386.       extern char erase_key;
  3387.       extern int get_from_macro;
  3388.       extern int alt_completion();
  3389. !     if (get_from_macro)
  3390. !     ok_val = AC_UNCHANGED;
  3391. !     else {
  3392. !     prompt(":");
  3393. !     ok_val = AC_PROMPT;
  3394. !     }
  3395.       
  3396.    again:
  3397.       
  3398. *** /usr/storm/nn6.3.4/menu.h    Mon Jul 10 13:36:21 1989
  3399. --- menu.h    Fri Sep  8 12:46:48 1989
  3400. ***************
  3401. *** 55,57 ****
  3402. --- 55,58 ----
  3403.   #define AC_REORDER    3    /* articles have been reordered */
  3404.   #define    AC_HEADER    4    /* update header line + Prompt */
  3405.   #define AC_KEYCMD    5    /* alt_cmd_key contains command */
  3406. + #define AC_UNCHANGED    6    /* no display changes */
  3407. *** /usr/storm/nn6.3.4/more.c    Mon Jul 10 13:36:22 1989
  3408. --- more.c    Fri Sep  8 12:46:48 1989
  3409. ***************
  3410. *** 6,19 ****
  3411. --- 6,23 ----
  3412.   #include "regexp.h"
  3413.   
  3414.   export int  monitor_mode = 0;
  3415. + export int  compress_mode = 0;
  3416.   export int  show_article_date = 1;
  3417.   export int  first_page_lines = 0;
  3418.   export int  overlap = 2;
  3419.   export int  mark_overlap = 0;
  3420.   export char *header_lines = NULL;
  3421. + export int  min_pv_window = 7;
  3422. + export int  wrap_headers = 6;
  3423.   
  3424.   import int  preview_window;
  3425.   import int  novice;
  3426. + import int  slow_mode;
  3427.   
  3428.   import char *delayed_msg;
  3429.   import long dl_msg_arg;
  3430. ***************
  3431. *** 49,54 ****
  3432. --- 53,61 ----
  3433.       'W', "Followup-To",    &news.ng_follow,    0,
  3434.       'X', "References",    &news.ng_ref,        0,
  3435.       'Y', "Summary",    &news.ng_summ,        0,
  3436. +     'd', "Date-Received", &news.ng_rdate,    0,
  3437. +     'n', "Newsgroups",    &news.ng_groups,    0,
  3438. +     'x', "Back-Ref",    &news.ng_bref,        0,
  3439.       0
  3440.   };
  3441.   
  3442. ***************
  3443. *** 154,160 ****
  3444.       in_menu_mode = 0;
  3445.       
  3446.       if (screen_offset)
  3447. !     if (preview_window < 1 && Lines - screen_offset < 6) 
  3448.           screen_offset = 0;
  3449.           else {
  3450.           so_printxy(0, screen_offset++, "%s: %s ", ah->sender, ah->subject);
  3451. --- 161,167 ----
  3452.       in_menu_mode = 0;
  3453.       
  3454.       if (screen_offset)
  3455. !     if (preview_window < 1 && Lines - screen_offset < min_pv_window) 
  3456.           screen_offset = 0;
  3457.           else {
  3458.           so_printxy(0, screen_offset++, "%s: %s ", ah->sender, ah->subject);
  3459. ***************
  3460. *** 184,190 ****
  3461.       if (lastl == 0) lastl = 1;    /* impossible ? */
  3462.       
  3463.       rot13 = 0;
  3464. !     compress_space = 0;
  3465.       last_ff_line = goto_line = -1, prev_goto = 1;
  3466.       match_lines = match_redraw = match_expr = 0;
  3467.       underline_line = -1;
  3468. --- 191,197 ----
  3469.       if (lastl == 0) lastl = 1;    /* impossible ? */
  3470.       
  3471.       rot13 = 0;
  3472. !     compress_space = compress_mode;
  3473.       last_ff_line = goto_line = -1, prev_goto = 1;
  3474.       match_lines = match_redraw = match_expr = 0;
  3475.       underline_line = -1;
  3476. ***************
  3477. *** 281,291 ****
  3478.               } else 
  3479.               if ((lp = *(hdef->news)) == NULL)
  3480.                   break;
  3481.               gotoxy(0, lno++);
  3482. -             c = strlen(hdef->text) + 2;
  3483. -             col = c + strlen(lp);
  3484. -             if (col > Columns) lp[Columns - c] = 0;
  3485.               printf("%s: ", hdef->text);
  3486.               switch (hdr_mode) {
  3487.                case 0:
  3488.               break;
  3489. --- 288,300 ----
  3490.               } else 
  3491.               if ((lp = *(hdef->news)) == NULL)
  3492.                   break;
  3493. +             if (*hdrline == 'n')
  3494. +             if (strchr(lp, ',') == NULL) break;
  3495. +             
  3496.               gotoxy(0, lno++);
  3497.               printf("%s: ", hdef->text);
  3498. +             c = col = strlen(hdef->text) + 2;
  3499. +          split_header_line:
  3500.               switch (hdr_mode) {
  3501.                case 0:
  3502.               break;
  3503. ***************
  3504. *** 296,302 ****
  3505.               underline(1);
  3506.               break;
  3507.               }
  3508. !             printf("%s", lp);
  3509.               switch (hdr_mode) {
  3510.                case 0:
  3511.               break;
  3512. --- 305,324 ----
  3513.               underline(1);
  3514.               break;
  3515.               }
  3516. !             while (*lp && c < Columns) {
  3517. !             if (isspace(*lp)) {
  3518. !                 while (lp[1] && isspace(lp[1])) lp++;
  3519. !                 if (wrap_headers > 0 &&
  3520. !                 (c + wrap_headers) >= Columns && 
  3521. !                 strlen(lp) >= wrap_headers) {
  3522. !                 lp++;
  3523. !                 break;
  3524. !                 }
  3525. !                 *lp = SP;
  3526. !             }
  3527. !             putchar(*lp++);
  3528. !             c++;
  3529. !             }            
  3530.               switch (hdr_mode) {
  3531.                case 0:
  3532.               break;
  3533. ***************
  3534. *** 307,312 ****
  3535. --- 329,339 ----
  3536.               underline(0);
  3537.               break;
  3538.               }
  3539. +             if (*lp && wrap_headers >= 0) {
  3540. +             gotoxy(col, lno++);
  3541. +             c = col;
  3542. +             goto split_header_line;
  3543. +             }
  3544.               break;
  3545.           }
  3546.           hdr_mode = 0;
  3547. ***************
  3548. *** 649,654 ****
  3549. --- 676,682 ----
  3550.       switch (c) {
  3551.        case K_UNBOUND:
  3552.       ding();
  3553. +      case K_INVALID:
  3554.       goto same_prompt;
  3555.       
  3556.        case K_REDRAW:
  3557. ***************
  3558. *** 693,698 ****
  3559. --- 721,729 ----
  3560.        case K_EXTENDED_CMD:
  3561.       switch (alt_command()) {
  3562.   
  3563. +      case AC_UNCHANGED:
  3564. +         goto same_prompt;
  3565. +         
  3566.        case AC_QUIT:
  3567.           more_return( MC_QUIT );
  3568.   
  3569. ***************
  3570. *** 733,746 ****
  3571.   
  3572.       goto Prompt;
  3573.       
  3574. -      case K_REPLY:
  3575.        case K_FOLLOW_UP:
  3576.        case K_MAIL_OR_FORWARD:
  3577. !     if (answer(ah, c, -1)) clrdisp();
  3578.       goto Prompt;
  3579.   
  3580.        case K_POST:
  3581. !     if (post_menu()) clrdisp();
  3582.       goto Prompt;
  3583.       
  3584.        case K_CANCEL:
  3585. --- 764,782 ----
  3586.   
  3587.       goto Prompt;
  3588.       
  3589.        case K_FOLLOW_UP:
  3590. + #ifdef NNTP_POST
  3591. +      if (use_nntp && nntp_no_post()) goto Prompt;
  3592. + #endif
  3593. +      case K_REPLY:
  3594.        case K_MAIL_OR_FORWARD:
  3595. !     if (answer(ah, c, -1)) 
  3596. !         if (slow_mode) clrdisp(); else goto redraw;
  3597.       goto Prompt;
  3598.   
  3599.        case K_POST:
  3600. !     if (post_menu())
  3601. !         if (slow_mode) clrdisp(); else goto redraw;
  3602.       goto Prompt;
  3603.       
  3604.        case K_CANCEL:
  3605. ***************
  3606. *** 760,766 ****
  3607.       more_return(MC_NEXTGROUP);
  3608.   
  3609.        case K_GROUP_OVERVIEW:
  3610. !     group_overview(0);
  3611.       goto redraw;
  3612.       
  3613.        case K_KILL_HANDLING:
  3614. --- 796,802 ----
  3615.       more_return(MC_NEXTGROUP);
  3616.   
  3617.        case K_GROUP_OVERVIEW:
  3618. !     group_overview(-1);
  3619.       goto redraw;
  3620.       
  3621.        case K_KILL_HANDLING:
  3622. ***************
  3623. *** 958,964 ****
  3624.   
  3625.        case K_LEAVE_ARTICLE:
  3626.       ah->flag &= ~(A_SELECT | A_AUTO | A_READ);
  3627. !     ah->flag |= A_LEAVE;
  3628.       /* fall thru */
  3629.   
  3630.        case K_NEXT_ARTICLE:
  3631. --- 994,1000 ----
  3632.   
  3633.        case K_LEAVE_ARTICLE:
  3634.       ah->flag &= ~(A_SELECT | A_AUTO | A_READ);
  3635. !     ah->flag |= (mode & MM_PREVIEW) ? A_SELECT : A_LEAVE;
  3636.       /* fall thru */
  3637.   
  3638.        case K_NEXT_ARTICLE:
  3639. *** /usr/storm/nn6.3.4/news.c    Mon Jul 10 13:36:23 1989
  3640. --- news.c    Fri Sep  8 12:46:48 1989
  3641. ***************
  3642. *** 54,59 ****
  3643. --- 54,60 ----
  3644.       news.ng_subj     = NULL;
  3645.       news.ng_groups     = NULL;
  3646.       news.ng_ref     = NULL;
  3647. +     news.ng_bref     = NULL;
  3648.   
  3649.       news.ng_xlines     = NULL;
  3650.   
  3651. ***************
  3652. *** 68,73 ****
  3653. --- 69,75 ----
  3654.           news.ng_appr     = NULL;
  3655.           news.ng_summ    = NULL;
  3656.           news.ng_date    = NULL;
  3657. +         news.ng_rdate    = NULL;
  3658.       }
  3659.   
  3660.       if (modes & GET_DATE_ONLY)
  3661. ***************
  3662. *** 176,184 ****
  3663. --- 178,191 ----
  3664.       check("pproved: ",     9, ng_appr);
  3665.       break;
  3666.   
  3667. +      case 'B':
  3668. +     check("ack-eferences: ",15, ng_bref);
  3669. +     break;
  3670.        case 'D':
  3671.       check("ate: ",          5, ng_date);
  3672.       if (!all) break;
  3673. +     check("ate-Received: ",    14, ng_rdate);
  3674.       check("istribution: ",     13, ng_dist);
  3675.       break;
  3676.   
  3677. *** /usr/storm/nn6.3.4/news.h    Mon Jul 10 13:36:24 1989
  3678. --- news.h    Fri Sep  8 12:46:48 1989
  3679. ***************
  3680. *** 25,30 ****
  3681. --- 25,33 ----
  3682.       char    *ng_summ;    /*   summary            */
  3683.       
  3684.       char    *ng_date;    /*   date            */
  3685. +     char    *ng_rdate;    /*   date-received (News 3)    */
  3686. +     char    *ng_bref;    /*   back-references (News 3)    */
  3687.       
  3688.       char    *ng_xlines;    /*   lines (from header)    */
  3689.       int    ng_lines;    /*   lines (decoded)        */
  3690. *** /usr/storm/nn6.3.4/nn.1    Mon Jul 10 13:36:25 1989
  3691. --- nn.1    Fri Sep  8 12:46:50 1989
  3692. ***************
  3693. *** 807,813 ****
  3694.   appear on the screen, and the menu or article text will be redrawn when
  3695.   the process is finished.
  3696.     The output is also saved in (or appended to) a file named
  3697. ! \fIUnshar.Result\fP in the unshar directory. 
  3698.   .TP
  3699.   \&\fB:decode\fP    {\fBdecode\fP}
  3700.   Decode \fIuuencoded\fP articles into binary files.  You will be
  3701. --- 807,818 ----
  3702.   appear on the screen, and the menu or article text will be redrawn when
  3703.   the process is finished.
  3704.     The output is also saved in (or appended to) a file named
  3705. ! \fIUnshar.Result\fP in the unshar directory.
  3706. !   The file specified in \fBunshar-header-file\fP (default
  3707. ! "Unshar.Headers") in the unshar directory will
  3708. ! contain the header and initial text (before the shar data) from the
  3709. ! article.  You can use the `G' {\fBgoto-group\fP} command to look at
  3710. ! the Unshar.Headers file.
  3711.   .TP
  3712.   \&\fB:decode\fP    {\fBdecode\fP}
  3713.   Decode \fIuuencoded\fP articles into binary files.  You will be
  3714. ***************
  3715. *** 824,829 ****
  3716. --- 829,837 ----
  3717.   decoded file using the checksum which is normally contained in the
  3718.   original article.  (Actually, you are also supposed to do this after
  3719.   decoding with a stand-alone uudecode program).
  3720. +   The header and initial information in the decoded articles are saved
  3721. + in the file specified in \fBdecode-header-file\fP (default
  3722. + "Decode.Headers") in the same directory as the decoded files.
  3723.   .LP
  3724.   In reading mode, the following keys can also be used to invoke the
  3725.   save commands:
  3726. ***************
  3727. *** 1581,1589 ****
  3728.   groups.  Any other
  3729.   .I mode
  3730.   results in a listing of the number of unread articles in all
  3731. ! subscribed groups (same as the
  3732. ! .B Y
  3733. ! command).
  3734.   .TP
  3735.   \fB:sort\fP [ \fImode\fP ]
  3736.   Reorder the articles on the menu according to 
  3737. --- 1589,1598 ----
  3738.   groups.  Any other
  3739.   .I mode
  3740.   results in a listing of the number of unread articles in all
  3741. ! subscribed groups including those you have suppressed with the `!'
  3742. ! symbol in the group presentation sequence.  To get just the currently
  3743. ! unread groups in the presentation sequence, use the `Y'
  3744. ! {\fBoverview\fP} command.
  3745.   .TP
  3746.   \fB:sort\fP [ \fImode\fP ]
  3747.   Reorder the articles on the menu according to 
  3748. ***************
  3749. *** 1700,1705 ****
  3750. --- 1709,1725 ----
  3751.   .LP
  3752.   The following variables are available:
  3753.   .TP
  3754. + \fBalso-subgroups\fP    (boolean, default true)
  3755. + When set, a group name in the presentation sequence will also cause
  3756. + all the subgroups of the group to be included, for example, comp.unix
  3757. + will also include comp.unix.questions, etc.  When \fBalso-subgroups\fP
  3758. + is not set, subgroups are only included if the group name is followed
  3759. + by a `.' in which case the main group is \fInot\fP included, i.e.
  3760. + `comp.unix' is not included when `comp.unix.' is specified in the
  3761. + presentation sequence, and vice-versa.  Following a group name by an
  3762. + asterisk `*', e.g. comp.unix*, will include the group as well as all
  3763. + subgroups independently of the setting of \fBalso-subgroups\fP.
  3764. + .TP
  3765.   \fBbackup\fP    (boolean, default true)
  3766.   Backup the rc file on start-up.  Setting 
  3767.   .B backup
  3768. ***************
  3769. *** 1709,1714 ****
  3770. --- 1729,1746 ----
  3771.   which articles have been read).  You can then exit
  3772.   \fInn\fP without updating the rc file with the \fB:q!\fP command.
  3773.   .TP
  3774. + \fBcollapse-subject\fP \fIoffset\fP    (integer, default 25)
  3775. + When set (non-negative), subject lines which are too long to be
  3776. + presented in full on the menus will be "collapsed" by removing a
  3777. + sufficient number of characters from the subject starting at the given
  3778. + \fIoffset\fP in the subject.  This is useful in source groups where
  3779. + the "Part (01/10)" string sometimes disappears from the menu.  When
  3780. + not set (or negative), the subjects are truncated.
  3781. + .TP
  3782. + \fBcolumns\fP \fIcol\fP    (integer, default screen width)
  3783. + This variable contains the screen width i.e. character positions per
  3784. + line.
  3785. + .TP
  3786.   \fBcomp1-key\fP \fIkey\fP    (key, default \fBspace\fP)
  3787.   The key which gives the first/next completion, and the default value
  3788.   when \fInn\fP is prompting for a string, e.g. a file name.
  3789. ***************
  3790. *** 1718,1731 ****
  3791.   completion for the next component
  3792.   when \fInn\fP is prompting for a string, e.g. a file name.
  3793.   .TP
  3794. ! \fBconfirm\fP        (boolean, default false)
  3795. ! In some cases, \fInn\fP will sleep one second (or more) when it has shown a
  3796. ! message to the user, e.g. in connection with macro debugging.  Setting
  3797. ! .B confirm
  3798. ! will cause \fInn\fP to
  3799. ! \fIwait\fP for you to confirm all messages by hitting any
  3800. ! key.  (It will show the symbol <> to indicate that it is awaiting
  3801. ! confirmation.)
  3802.   .TP
  3803.   \fBconfirm-append\fP        (boolean, default false) 
  3804.   Normally when
  3805. --- 1750,1760 ----
  3806.   completion for the next component
  3807.   when \fInn\fP is prompting for a string, e.g. a file name.
  3808.   .TP
  3809. ! \fBcompress\fP        (boolean, default false)
  3810. ! This variable controls whether text compression (see the
  3811. ! \fBcompress\fP command) is turned on or off when an article is
  3812. ! shown.  The compression is still toggled for the current article with
  3813. ! the \fBcompress\fP command key.
  3814.   .TP
  3815.   \fBconfirm-append\fP        (boolean, default false) 
  3816.   Normally when
  3817. ***************
  3818. *** 1735,1740 ****
  3819. --- 1764,1785 ----
  3820.   is set, you will also be asked for confirmation before appending an
  3821.   article to an existing file.
  3822.   .TP
  3823. + \fBconfirm-auto-quit\fP        (boolean, default false)
  3824. + When set, \fInn\fP will ask for confirmation before quitting after
  3825. + having read the last group.  If not confirmed, \fInn\fP will recycle
  3826. + the presentation sequence looking for groups that were skipped with
  3827. + the `N' {\fBnext-group\fP} command.  But it will not look for new
  3828. + articles arrived since the invokation of \fInn\fP.
  3829. + .TP
  3830. + \fBconfirm-messages\fP        (boolean, default false)
  3831. + In some cases, \fInn\fP will sleep one second (or more) when it has shown a
  3832. + message to the user, e.g. in connection with macro debugging.  Setting
  3833. + .B confirm-messages
  3834. + will cause \fInn\fP to
  3835. + \fIwait\fP for you to confirm all messages by hitting any
  3836. + key.  (It will show the symbol <> to indicate that it is awaiting
  3837. + confirmation.)
  3838. + .TP
  3839.   \fBcross-post\fP        (boolean, default false) 
  3840.   Normally, \fInn\fP will only show cross-posted articles in the first
  3841.   subscribed group on the Newsgroups: line.  When
  3842. ***************
  3843. *** 1749,1754 ****
  3844. --- 1794,1806 ----
  3845.   \fBdebug\fP \fImask\fP    (integer, default 0)
  3846.   Look in the source if you are going to use this.
  3847.   .TP
  3848. + \fBdecode-header-file\fP \fIfile\fP    (string, default "Decode.Headers")
  3849. + The name of the file in which the header and initial text of articles
  3850. + decoded with the \fB:decode\fP command is saved.  Unless the file name
  3851. + starts with a `/', the file will be created in the same directory as
  3852. + the decoded files.  The information is not saved if this variable is
  3853. + not set.
  3854. + .TP
  3855.   \fBdefault-distribution\fP \fIdistr\fP    (string, default not set)
  3856.   The distribution to use as the default suggestion when posting
  3857.   articles using the \fBpost\fP command.  If it is not set, the
  3858. ***************
  3859. *** 1761,1771 ****
  3860.   mode.
  3861.   .TP
  3862.   \fBdelay-redraw\fP        (boolean, default false)
  3863. ! Normally, \fInn\fP will redraw the screen immediately after an
  3864. ! extended command (:command) which cleared the screen.  If
  3865. ! \fBdelay-redraw\fP is set \fInn\fP will prompt for a new command
  3866. ! without redrawing the screen; it is redrawn when you give an empty
  3867. ! reply.
  3868.   .TP
  3869.   \fBerase-key\fP \fIkey\fP    (key, default tty erase key)
  3870.   The key which erases the last input character
  3871. --- 1813,1822 ----
  3872.   mode.
  3873.   .TP
  3874.   \fBdelay-redraw\fP        (boolean, default false)
  3875. ! Normally, \fInn\fP will redraw the screen after extended
  3876. ! commands (:cmd) that clear the screen.  When \fBdelay-redraw\fP is set
  3877. ! \fInn\fP will prompt for another extended command instead of redrawing
  3878. ! the screen (hit \fBreturn\fP to redraw).
  3879.   .TP
  3880.   \fBerase-key\fP \fIkey\fP    (key, default tty erase key)
  3881.   The key which erases the last input character
  3882. ***************
  3883. *** 1835,1840 ****
  3884. --- 1886,1894 ----
  3885.   as read.  This is useful to get up-to-date quickly if you have not
  3886.   read news for a longer period.
  3887.   .TP
  3888. + \fBlines\fP \fIlin\fP    (integer, default screen hight)
  3889. + This variable contains the screen hight i.e. number of lines.
  3890. + .TP
  3891.   \fBlong-menu\fP        (boolean, default false)
  3892.   If set \fInn\fP will not put an empty line after the header line and
  3893.   an empty line before the prompt line; this gives you two extra menu
  3894. ***************
  3895. *** 1876,1881 ****
  3896. --- 1930,1943 ----
  3897.   of the terminal if possible) to indicate the end of the overlap (see the
  3898.   \fBoverlap\fP variable).
  3899.   .TP
  3900. + \fBmin-window\fP \fIsize\fP    (integer, default 7)
  3901. + When the \fBwindow\fP variable is not set, \fInn\fP will clear the
  3902. + screen to preview an article if there are less than \fIsize\fP unused
  3903. + lines at the bottom of the menu screen.
  3904. + .TP
  3905. + \fBmmdf-format\fP    (boolean, default false)
  3906. + When set, \fInn\fP will save articles in MMDF format.
  3907. + .TP
  3908.   \fBmonitor\fP        (boolean, default false)
  3909.   When set, \fInn\fP will show 
  3910.   .I all
  3911. ***************
  3912. *** 1941,1946 ****
  3913. --- 2003,2021 ----
  3914.   Instead it uses the save file specified for the current group in the
  3915.   init file or the default save file.
  3916.   .TP
  3917. + \fBre-layout\fP \fIN\fP        (integer, default 0)
  3918. + Normally on the menu, \fInn\fP will prefix the subject a number of
  3919. + `>'s corresponding to the number of references on the References:
  3920. + line.  The \fBre-layout\fP variable may be set to use a different
  3921. + prefix on the subjects:
  3922. + .br
  3923. + .nf
  3924. +     0:  One `>' per reference is shown (default).
  3925. +     1:  Only a single `>' is shown.
  3926. +     2:  The number of references is shown as `n>'
  3927. +     3:  A single Re: is shown.
  3928. + .fi
  3929. + .TP
  3930.   \fBrecord\fP \fIfile\fP    (string, no default)
  3931.   Setting this 
  3932.   .I pseudo
  3933. ***************
  3934. *** 1976,1981 ****
  3935. --- 2051,2074 ----
  3936.   .B \-Q
  3937.   option.
  3938.   .TP
  3939. + \fBslow-mode\fP        (boolean, default false)
  3940. + When set, \fInn\fP will cut down on the screen output to give better
  3941. + response time at low speed.
  3942. + Normally, \fInn\fP will use standout mode (if possible) to mark
  3943. + selected articles on the menu, but when \fBslow-mode\fP is set, \fInn\fP will
  3944. + just put an asterisk `*' next to the article identifier on selected
  3945. + articles.  Also when \fBslow-mode\fP is set \fInn\fP will avoid
  3946. + redrawing the screen in the following cases:  After a \fBgoto-group\fP
  3947. + command an empty menu is shown (hit \fBspace\fP to make it appear),
  3948. + and after responding to an article, only the prompt line is shown (use
  3949. + ^L to redraw the screen).  To avoid redrawing the screen aftern an
  3950. + extended command, set the \fBdelay-redraw\fP variable as well.
  3951. + .TP
  3952. + \fBslow-speed\fP \fIspeed\fP    (integer, default 1200)
  3953. + If the terminal is running at this baud rate or lower, the \fBon
  3954. + slow\fP (see the section on init files) condition will be true, and
  3955. + the \fBon fast\fP will be false (and vice-versa).
  3956. + .TP
  3957.   \fBsort\fP        (boolean, default true)
  3958.   When set, \fInn\fP will sort articles according to subject (and age
  3959.   for identical subjects).  Otherwise, articles will be presented in
  3960. ***************
  3961. *** 2006,2015 ****
  3962.   .I sysline (1)
  3963.   utility.
  3964.   .TP
  3965.   \fBwindow\fP \fIsize\fP    (integer, default not set)
  3966.   When set, \fInn\fP will reserve the last \fIsize\fP lines of the menu
  3967.   screen for a preview window.  If not set, \fInn\fP will clear the
  3968. ! screen to preview an article if there are too few empty lines at the
  3969.   bottom of the screen.  As a side effect, it can also be used to reduce
  3970.   the size of the menus, which may be useful on slow terminals.
  3971.   .TP
  3972. --- 2099,2123 ----
  3973.   .I sysline (1)
  3974.   utility.
  3975.   .TP
  3976. + \fBunshar-header-file\fP \fIfile\fP    (string, default "Unshar.Headers")
  3977. + The name of the file in which the header and initial text of articles
  3978. + unpacked with the \fB:unshar\fP command is saved.  Unless the file name
  3979. + starts with a `/', the file will be created in the same directory as
  3980. + the unpacked files.  The information is not saved if this variable is
  3981. + not set.  Setting it to "Unshar.Result" will cause the headers and the
  3982. + results from the unpacking process to be merged in a meaningful way
  3983. + (unless \fBmmdf-format\fP is set).
  3984. + .TP
  3985. + \fBvisible-bell\fP    (boolean, default true)
  3986. + When set, \fInn\fP will flash the screeen instead of "ringing the
  3987. + bell" if the visible bell (flash) capability is defined in the
  3988. + termcap/terminfo database. 
  3989. + .TP
  3990.   \fBwindow\fP \fIsize\fP    (integer, default not set)
  3991.   When set, \fInn\fP will reserve the last \fIsize\fP lines of the menu
  3992.   screen for a preview window.  If not set, \fInn\fP will clear the
  3993. ! screen to preview an article if there are less than \fBmin-window\fP
  3994. ! lines at the
  3995.   bottom of the screen.  As a side effect, it can also be used to reduce
  3996.   the size of the menus, which may be useful on slow terminals.
  3997.   .TP
  3998. ***************
  3999. *** 2017,2022 ****
  4000. --- 2125,2138 ----
  4001.   The key which erases the last input component or word
  4002.   when \fInn\fP is prompting for a string, e.g. the last name in a path
  4003.   name.
  4004. + .TP
  4005. + \fBwrap-header-margin\fP \fIsize\fP    (integer, default 6)
  4006. + When set (non-negative), the customized header fields specified in
  4007. + \fBheader-lines\fP will be split across several lines if they don't
  4008. + fit on one line.  When \fIsize\fP is greater than zero, lines will be
  4009. + split at the first space occurring in the last \fIsize\fP columns of
  4010. + the line.  If not set (or negative), long header lines will be
  4011. + truncated if they don't fit on a single line.
  4012.   .SH CUSTOMIZED ARTICLE HEADER PRESENTATION
  4013.   Normally, \fInn\fP will just print a (high-lighted) single line header
  4014.   containing the author, subject, and date (optional) of the article
  4015. ***************
  4016. *** 2046,2051 ****
  4017. --- 2162,2169 ----
  4018.   .br
  4019.   \fBD\fP    Date:
  4020.   .br
  4021. + \fBd\fP    Date-Received:
  4022. + .br
  4023.   \fBF\fP    From:
  4024.   .br
  4025.   \fBI\fP    Message-Id:
  4026. ***************
  4027. *** 2056,2061 ****
  4028. --- 2174,2181 ----
  4029.   .br
  4030.   \fBN\fP    Newsgroups:
  4031.   .br
  4032. + \fBn\fP    Newsgroups:   (but only if cross posted)
  4033. + .br
  4034.   \fBO\fP    Organization:
  4035.   .br
  4036.   \fBP\fP    Path:
  4037. ***************
  4038. *** 2068,2073 ****
  4039. --- 2188,2195 ----
  4040.   .br
  4041.   \fBX\fP    References:
  4042.   .br
  4043. + \fBx\fP    Back-References:
  4044. + .br
  4045.   \fBY\fP    Summary:
  4046.   .in -8n
  4047.   .DT
  4048. ***************
  4049. *** 2185,2191 ****
  4050.   Reserve \fIN\fP lines of the menu screen for a preview window.  If
  4051.   \fIN\fP is omitted, the preview window is set to 5 lines.
  4052.   .TP
  4053. ! \-\fBW\fP    {\fBtoggle confirm\fP}
  4054.   [Don't] Wait for confirmation on all messages.
  4055.   .TP
  4056.   \-\fBx\fP[\fIN\fP]    {\fBset old N\fP}
  4057. --- 2307,2313 ----
  4058.   Reserve \fIN\fP lines of the menu screen for a preview window.  If
  4059.   \fIN\fP is omitted, the preview window is set to 5 lines.
  4060.   .TP
  4061. ! \-\fBW\fP    {\fBtoggle confirm-messages\fP}
  4062.   [Don't] Wait for confirmation on all messages.
  4063.   .TP
  4064.   \-\fBx\fP[\fIN\fP]    {\fBset old N\fP}
  4065. ***************
  4066. *** 2275,2280 ****
  4067. --- 2397,2411 ----
  4068.   command, the following command is used:
  4069.   .sp 0.5v
  4070.       map menu #0 select
  4071. + .sp 0.5v
  4072. + To remap a key to select a specific article on the menu (which the `a'
  4073. + through `z' keys do by default), the \fIcommand\fP must be specified
  4074. + as `\fBarticle\fP \fIN\fP' where \fIN\fP is the entry number on the
  4075. + menu counted from zero (i.e. a=0, b=1, ..., z=25, 0=26, ..., 9=35).
  4076. + For example, to map `J' to select article `j', the following
  4077. + command is used:
  4078. + .sp 0.5v
  4079. +     map menu J article 9
  4080.   .TP
  4081.   .B The reading mode key binding table
  4082.   This table defines for each key which command should be invoked when
  4083. ***************
  4084. *** 2286,2291 ****
  4085. --- 2417,2437 ----
  4086.   in reading mode is:
  4087.   .sp 0.5v
  4088.       \fBmap show\fP \fIkey command\fP
  4089. + .TP
  4090. + .B Mapping keys in both modes
  4091. + Using the pseudo-keymap `both', it is possible to map a key to a
  4092. + command in both selection and reading mode at once.  For example, to
  4093. + map the home key to macro number 5 in both modes, the following
  4094. + command can be used:
  4095. + .sp 0.5v
  4096. +     map both #0 macro 5
  4097. + .TP
  4098. + .B Aliasing
  4099. + A key can also be mapped directly to the command currently bound to
  4100. + another key.  Later remapping of the other key will not change the
  4101. + mapping of the `aliased' key.  This is done using the following command:
  4102. + .sp 0.5v
  4103. +     map \fIkeymap new-key\fP \fBas\fP \fIold-key\fP
  4104.   .LP
  4105.   Keys and character names are specified using the following notation:
  4106.   .TP
  4107. ***************
  4108. *** 2339,2344 ****
  4109. --- 2485,2492 ----
  4110.   .br
  4111.   \fBadvance-group\fP    A     A 
  4112.   .br
  4113. + \fBarticle\fP \fIN\fP    a-z0-9     \fBnix\fP 
  4114. + .br
  4115.   \fBback-article\fP    \fBnix\fP     b 
  4116.   .br
  4117.   \fBback-group\fP    B     B 
  4118. ***************
  4119. *** 2477,2484 ****
  4120.   .B :define
  4121.   command, macro definitions are normally placed in the 
  4122.   .I init
  4123. ! file.  Macros are numbered from 0 to 31, i.e. it is possible to define
  4124. ! a total of 32 different macros.
  4125.   .LP
  4126.   To define macro number \fIM\fP, the following construction is used
  4127.   (the line breaks are mandatory):
  4128. --- 2625,2632 ----
  4129.   .B :define
  4130.   command, macro definitions are normally placed in the 
  4131.   .I init
  4132. ! file.  Macros are numbered from 0 to 100, i.e. it is possible to define
  4133. ! a total of 101 different macros.
  4134.   .LP
  4135.   To define macro number \fIM\fP, the following construction is used
  4136.   (the line breaks are mandatory):
  4137. ***************
  4138. *** 2593,2598 ****
  4139. --- 2741,2757 ----
  4140.   must be enclosed in double quotes.  Example:
  4141.   .br
  4142.       \fBprompt\fP "Enter recipient name"
  4143. + .br
  4144. + When the macro terminates, the original prompt shown on entry to the
  4145. + macro will automatically be redrawn.  If this is not desireable (e.g.
  4146. + if the macro goes from selection to reading mode), the redrawing of
  4147. + the prompt can be disabled by using a \fBprompt\fP command with an
  4148. + empty \fIstring\fP ("").  Example:
  4149. + .nf
  4150. +     \fBprompt\fP "Enter reading mode?" # old prompt is saved
  4151. +     ?no return # and old prompt is restored
  4152. +     read-skip       # changes the prompt
  4153. +     \fBprompt\fP "" # so forget old prompt
  4154.   .TP
  4155.   \fBecho\fP \fIstring\fP
  4156.   Display the \fIstring\fP in the prompt line for a short period.  Example:
  4157. ***************
  4158. *** 2692,2697 ****
  4159. --- 2851,2861 ----
  4160.       cd ~/News
  4161.   .fi
  4162.   .TP
  4163. + .B Command groups
  4164. + The init file can contain groups of commands which are executed under
  4165. + special conditions.  The command groups are described in the section 
  4166. + on command groups below.
  4167. + .TP
  4168.   .B The news group presentation sequence
  4169.   The 
  4170.   .I last
  4171. ***************
  4172. *** 2702,2707 ****
  4173. --- 2866,2934 ----
  4174.   .LP
  4175.   Both init files may contain a presentation sequence.  In this case,
  4176.   the global sequence is \fIappended\fP to the private sequence.
  4177. + .SH COMMAND GROUPS
  4178. + Command groups may only occur in the init file, and they provide a way
  4179. + to have series of commands executed at certain points during news reading.
  4180. + .LP
  4181. + In release 6.3.5, these possibilities are still rather rudimentary, and
  4182. + a mixture of macro syntax and normal init file syntax is used
  4183. + depending on whether the command group is only executed on start-up or
  4184. + several times during the \fInn\fP session.
  4185. + .LP
  4186. + A command group begins with the word \fBon\fP and
  4187. + ends with the word \fBend\fP.  The \fBon\fP symbol must followed by 
  4188. + one of the following identifiers denoting when the group is executed:
  4189. + .sp 0.5v
  4190. + .nf
  4191. +     \fBon\fP ...
  4192. +     commands
  4193. +     \fBend\fP
  4194. + .fi
  4195. + .sp 0.5v
  4196. + The following command groups may be defined:
  4197. + .TP
  4198. + \fBon slow\fP
  4199. + .br
  4200. + The commands (init file syntax) in the group are executed only if the
  4201. + current terminal output speed is less than or equal to the baud rate
  4202. + set in the \fBslow-speed\fP variable.  This can be used to optimize
  4203. + the user-interface for slow terminals by setting suitable variables:
  4204. + .sp 0.5v
  4205. + .nf
  4206. +     \fBon slow\fP
  4207. +         set slow-mode
  4208. +         set delay-redraw
  4209. +         unset visible-bell
  4210. +         set compress
  4211. +         unset header-lines
  4212. +         set stop 5
  4213. +         set window 10
  4214. +     \fBend\fP
  4215. + .fi
  4216. + .TP
  4217. + \fBon fast\fP
  4218. + .br
  4219. + Same as \fBon slow\fP except that the commands are only executed when
  4220. + the terminal is running at a speed above the \fBslow-speed\fP value.
  4221. + .TP
  4222. + \fBon entry\fP
  4223. + .br
  4224. + These commands (macro format!) are executed every time \fInn\fP enters a
  4225. + news group.  The `:set' and `:unset' commands at the beginning of the
  4226. + command group are executed \fIbefore\fP \fInn\fP collects the articles
  4227. + in the group, so it is possible to set variables like
  4228. + \fBcross-post\fP.  The other commands, and :set/:unset commands that
  4229. + follows a command of another type will be executed immediately
  4230. + \fIafter\fP the first menu page is presented.
  4231. + .sp 0.5v
  4232. + .nf
  4233. +     \fBon entry\fP
  4234. +         :unset cross-post
  4235. +     \fBend\fP        
  4236. + .fi
  4237. + .sp 0.5v
  4238. + The `entry' command group is \fInot\fP executed if the group has its
  4239. + own entry action specified in the presentation sequence (see below).
  4240.   .SH GROUP PRESENTATION SEQUENCE
  4241.   News groups are normally presented in the sequence defined in the
  4242.   system-wide 
  4243. ***************
  4244. *** 2739,2746 ****
  4245.   has not been disabled (as described below).
  4246.   .LP
  4247.   Each group name may be followed by a file or folder name (must start
  4248. ! with either of / . ~ or +) which will specify the default save file
  4249. ! for that group (and its subgroups).  A single "+" following the group
  4250.   name is an abbreviation for the last save file name used.
  4251.   .LP
  4252.   When an article is saved, the default save name will be used as the
  4253. --- 2966,2973 ----
  4254.   has not been disabled (as described below).
  4255.   .LP
  4256.   Each group name may be followed by a file or folder name (must start
  4257. ! with either of `/' `~' or `+') which will specify the default save file
  4258. ! for that group (and its subgroups).  A single `+' following the group
  4259.   name is an abbreviation for the last save file name used.
  4260.   .LP
  4261.   When an article is saved, the default save name will be used as the
  4262. ***************
  4263. *** 2748,2757 ****
  4264.   therefore does not need to be be a complete file name (unless you use
  4265.   the quick save mode).
  4266.   .LP
  4267. ! The following meta notation can be used in a sequence file:
  4268.   .TP
  4269.   group.name
  4270. ! Append the group (and its subgroups) to the presentation sequence list.
  4271.   .TP
  4272.   \&! group.name
  4273.   Completely ignore the group (and its subgroups)
  4274. --- 2975,3040 ----
  4275.   therefore does not need to be be a complete file name (unless you use
  4276.   the quick save mode).
  4277.   .LP
  4278. ! Each group name may also be associated
  4279. ! with a so-called \fBentry action\fP.  This is basically an (unnamed)
  4280. ! macro which is invoked on entry to the group (following the same rules
  4281. ! as the `on entry' command group related to :set and :unset commands).
  4282. ! .LP
  4283. ! The entry action begins with a left parenthesis `\fB(\fP' and ends
  4284. ! with a right parenthesis `\fB)\fP' on an otherwise empty line:
  4285. ! .sp 0.5v
  4286. ! .nf
  4287. !     comp.sources. +src/$L/ (
  4288. !         :set cross-post
  4289. !     )
  4290. ! .fi
  4291. ! .sp 0.5v
  4292. ! The last entry action can be repeated by specifying an empty set of
  4293. ! parenthesis, e.g. 
  4294. ! .sp 0.5v
  4295. !     comp.unix. +unix ()
  4296. ! .sp 0.5v
  4297. ! The entry action of a preceding group in the sequence can be
  4298. ! associated with the current group(s) by specifying the name of the
  4299. ! group in the parentheses instead of the commands, e.g.
  4300. ! .sp 0.5v
  4301. !     comp.unix. +unix (comp.sources.unix)
  4302. ! .sp 0.5v
  4303. ! A macro can also be associated with the entry action by specifying its
  4304. ! number in the same way as the group name above, e.g.
  4305. ! .sp 0.5v
  4306. !     rec.music. +music (30)
  4307. ! .sp 0.5v
  4308. ! Notice that it is the
  4309. ! \fIcurrent\fP definition of the macro which is associated with the
  4310. ! group, so if the macro is later redefined with the `:define' command,
  4311. ! it will not have any effect on the entry action.
  4312. ! .LP
  4313. ! Group names can be specified using the following notations:
  4314.   .TP
  4315.   group.name
  4316. ! Append the group (if it exists) to the presentation sequence list.  If
  4317. ! \fBalso-subgroups\fP is set (default), all subscribed subgroups of the
  4318. ! group will be included as well (if there are any).  Examples: "comp",
  4319. ! "comp.unix", "comp.unix.questions".  If the group does not exits (e.g.
  4320. ! "comp"), the subgroups will be included even when \fBalso-subgroups\fP
  4321. ! is not set, i.e. "comp" is equivalent to "comp.".
  4322. ! .TP
  4323. ! group.name.
  4324. ! Append the subgroups of the specified group to the presentation
  4325. ! sequence.  The group itself (if it exists) is not included.
  4326. ! Examples: "comp.", "comp.unix.".
  4327. ! .TP
  4328. ! .group.name
  4329. ! Append the groups whose name ends with the specified name to the
  4330. ! sequence.  Example: ".test".
  4331. ! .TP
  4332. ! group.name*
  4333. ! Append the group and its subgroups to the presentation sequence list
  4334. ! (even when \fBalso-subgroups\fP is not set).  Example: "comp.unix*".
  4335. ! .LP
  4336. ! The following meta notation can be used in a sequence file.  The
  4337. ! group.name can be specified using any of the forms described above:
  4338.   .TP
  4339.   \&! group.name
  4340.   Completely ignore the group (and its subgroups)
  4341. *** /usr/storm/nn6.3.4/nn.c    Mon Jul 10 13:36:28 1989
  4342. --- nn.c    Fri Sep  8 12:46:50 1989
  4343. ***************
  4344. *** 18,23 ****
  4345. --- 18,24 ----
  4346.   export int
  4347.       article_limit = -1,
  4348.       also_read_articles = 0,
  4349. +     conf_auto_quit = 0,
  4350.       do_kill_handling = 1,
  4351.       group_name_args = 0,
  4352.       merged_menu = 0,
  4353. ***************
  4354. *** 123,129 ****
  4355.       if (enter_admin_mode) {
  4356.       if (argc == 1) {
  4357.           init_term();
  4358. !         visit_init_file();
  4359.       }
  4360.       open_master(OPEN_READ);
  4361.       visit_active_file();
  4362. --- 124,130 ----
  4363.       if (enter_admin_mode) {
  4364.       if (argc == 1) {
  4365.           init_term();
  4366. !         visit_init_file(0);
  4367.       }
  4368.       open_master(OPEN_READ);
  4369.       visit_active_file();
  4370. ***************
  4371. *** 131,144 ****
  4372.       nn_exit(0);
  4373.       }
  4374.   
  4375. !     if (check_news)
  4376. !     parse_options(argc, argv, (char *)NULL, check_options, "");    
  4377. !     else
  4378.       if (!emacs_slave_mode) {
  4379.       init_term();
  4380.   
  4381.       if (argc < 2 || strncmp(argv[1], "-I", 2))
  4382. !         visit_init_file();
  4383.   
  4384.       group_name_args =
  4385.           parse_options(argc, argv, (char *)NULL,
  4386. --- 132,147 ----
  4387.       nn_exit(0);
  4388.       }
  4389.   
  4390. !     if (check_news) {
  4391. !     group_name_args =
  4392. !         parse_options(argc, argv, (char *)NULL, check_options, " [group | [+]folder]...");
  4393. !     visit_init_file(1);
  4394. !     } else
  4395.       if (!emacs_slave_mode) {
  4396.       init_term();
  4397.   
  4398.       if (argc < 2 || strncmp(argv[1], "-I", 2))
  4399. !         visit_init_file(0);
  4400.   
  4401.       group_name_args =
  4402.           parse_options(argc, argv, (char *)NULL,
  4403. ***************
  4404. *** 172,177 ****
  4405. --- 175,185 ----
  4406.       
  4407.       visit_rc_file();
  4408.   
  4409. +     if (group_name_args > 0)
  4410. +     named_group_sequence(argv + 1);
  4411. +     else
  4412. +     normal_group_sequence();
  4413.       count_unread_articles(report_group_names);
  4414.   
  4415.       if (emacs_slave_mode)
  4416. ***************
  4417. *** 207,217 ****
  4418.       if (do_kill_handling)
  4419.       do_kill_handling = init_kill();
  4420.       
  4421. -     if (group_name_args > 0)
  4422. -     named_group_sequence(argv + 1);
  4423. -     else
  4424. -     normal_group_sequence();
  4425.       if (emacs_slave_mode) {
  4426.       emacs_mode();
  4427.       goto out;
  4428. --- 215,220 ----
  4429. ***************
  4430. *** 288,293 ****
  4431. --- 291,297 ----
  4432.       loop++;
  4433.   
  4434.       unset_raw();
  4435. +     visual_off();
  4436.       
  4437.   #ifdef NNTP
  4438.       nntp_cleanup();
  4439. ***************
  4440. *** 302,323 ****
  4441.   
  4442.   static read_news(mode)
  4443.   {
  4444. !     register group_header *cur, *prev, *tmp;
  4445.       int menu_cmd;
  4446.       int must_clear = 0, did_jump = 0;
  4447.       extern int menu();
  4448.   
  4449.       prev = group_sequence;
  4450.       cur = group_sequence;
  4451. !     
  4452. !     while (cur != NULL || did_jump) {
  4453.       if (s_hangup) break;
  4454.       
  4455. !     if (cur == NULL) {
  4456. !         did_jump = 0;
  4457. !         cur = group_sequence;
  4458. !         continue;
  4459.       }
  4460.       
  4461.       if (!also_read_articles)
  4462. --- 306,346 ----
  4463.   
  4464.   static read_news(mode)
  4465.   {
  4466. !     register group_header *cur, *prev, *tmp, *after_loop;
  4467.       int menu_cmd;
  4468.       int must_clear = 0, did_jump = 0;
  4469.       extern int menu();
  4470.   
  4471.       prev = group_sequence;
  4472.       cur = group_sequence;
  4473. !     after_loop = NULL;
  4474. !     
  4475. !     while (cur != NULL || did_jump || conf_auto_quit) {
  4476.       if (s_hangup) break;
  4477.       
  4478. !     if (mode == 0 && cur == NULL) {
  4479. !         if (after_loop != NULL) {
  4480. !         cur = after_loop;
  4481. !         after_loop = NULL;
  4482. !         cur->last_article = cur->first_article;
  4483. !         continue;
  4484. !         }
  4485. !         if (did_jump) {
  4486. !         did_jump = 0;
  4487. !         cur = group_sequence;
  4488. !         continue;
  4489. !         }
  4490. !         if (!must_clear) return 0;
  4491. !         prompt("\1LAST GROUP READ.  QUIT NOW?\1");
  4492. !         switch (yes(1)) {
  4493. !          case 1: 
  4494. !         return 1;
  4495. !          case 0: 
  4496. !         cur = group_sequence;
  4497. !          default:
  4498. !         after_loop = prev;
  4499. !         continue;
  4500. !         }
  4501.       }
  4502.       
  4503.       if (!also_read_articles)
  4504. ***************
  4505. *** 367,375 ****
  4506.           menu_cmd = group_menu(cur, (article_number)(-1), 
  4507.                     match_subject, do_kill_handling, menu);
  4508.   
  4509. !     if (menu_cmd != ME_NO_ARTICLES)
  4510.           must_clear++;
  4511. !     
  4512.       switch (menu_cmd) {
  4513.           
  4514.        case ME_PREV:
  4515. --- 390,400 ----
  4516.           menu_cmd = group_menu(cur, (article_number)(-1), 
  4517.                     match_subject, do_kill_handling, menu);
  4518.   
  4519. !     if (menu_cmd != ME_NO_ARTICLES) {
  4520. !         after_loop = NULL;
  4521.           must_clear++;
  4522. !     }
  4523.       switch (menu_cmd) {
  4524.           
  4525.        case ME_PREV:
  4526. *** /usr/storm/nn6.3.2/nntidy.sh    Wed Jun 28 20:08:03 1989
  4527. --- nntidy.sh    Fri Sep  8 12:46:51 1989
  4528. ***************
  4529. *** 18,24 ****
  4530.   mv rc rc.bak1
  4531.   
  4532.   {
  4533. !     cat ${ACTIVE}
  4534.       echo EOA
  4535.       cat rc.bak1
  4536.   
  4537. --- 18,24 ----
  4538.   mv rc rc.bak1
  4539.   
  4540.   {
  4541. !     cat ${2-$ACTIVE}
  4542.       echo EOA
  4543.       cat rc.bak1
  4544.   
  4545. *** /usr/storm/nn6.3.2/nntp.c    Wed Jun 28 20:08:04 1989
  4546. --- nntp.c    Fri Sep  8 12:46:51 1989
  4547. ***************
  4548. *** 6,12 ****
  4549.    *
  4550.    * Rene' Seindal (seindal@diku.dk) Thu Dec  1 18:41:23 1988
  4551.    *
  4552. !  * Last change: Tue May 23 18:38:49 1989
  4553.    */
  4554.   
  4555.   
  4556. --- 6,12 ----
  4557.    *
  4558.    * Rene' Seindal (seindal@diku.dk) Thu Dec  1 18:41:23 1988
  4559.    *
  4560. !  * Last change: Fri Jul  7 18:56:00 1989
  4561.    */
  4562.   
  4563.   
  4564. ***************
  4565. *** 22,29 ****
  4566.   #define NNTPCACHE    10
  4567.   #endif
  4568.   
  4569. - #undef DEBUG
  4570.   #ifdef NNTP
  4571.   #include <stdio.h>
  4572.   #include "nntp.h"
  4573. --- 22,27 ----
  4574. ***************
  4575. *** 32,59 ****
  4576.   #include <netdb.h>
  4577.   
  4578.   /* This is necessary due to the definitions in m-XXX.h */
  4579. ! #ifndef NETWORK_DATABASE
  4580. ! #include <netinet/in.h>
  4581. ! #else
  4582. ! #ifdef NETWORK_BYTE_ORDER
  4583.   #include <netinet/in.h>
  4584.   #endif
  4585. - #endif
  4586.   
  4587.   export char nntp_server[256];    /* name of nntp server */
  4588.   export int use_nntp = 0;    /* bool: t iff we use nntp */
  4589. ! export int nntp_failed = 0;    /* bool: t iff connection is broken */
  4590. !                 /*  in nntp_get_article() or nntp_get_active() */
  4591.   import int silent;
  4592.   import char news_active[];
  4593.   
  4594. ! extern int errno, sys_nerr;
  4595. ! extern char *sys_errlist[];
  4596.   
  4597.   #define syserr() (errno >= 0 && errno < sys_nerr ? \
  4598. !           sys_errlist[errno] : "Illegal error.")
  4599.   
  4600. ! extern char *mktemp();
  4601.   
  4602.   static FILE *nntp_in = NULL;        /* fp for reading from server */
  4603.   static FILE *nntp_out = NULL;        /* fp for writing to server */
  4604. --- 30,54 ----
  4605.   #include <netdb.h>
  4606.   
  4607.   /* This is necessary due to the definitions in m-XXX.h */
  4608. ! #if !defined(NETWORK_DATABASE) || defined(NETWORK_BYTE_ORDER)
  4609.   #include <netinet/in.h>
  4610.   #endif
  4611.   
  4612.   export char nntp_server[256];    /* name of nntp server */
  4613.   export int use_nntp = 0;    /* bool: t iff we use nntp */
  4614. ! export int nntp_failed = 0;    /* bool: t iff connection is broken
  4615. !                    in nntp_get_article() or nntp_get_active() */
  4616.   import int silent;
  4617.   import char news_active[];
  4618.   
  4619. ! import int errno, sys_nerr;
  4620. ! import char *sys_errlist[];
  4621.   
  4622.   #define syserr() (errno >= 0 && errno < sys_nerr ? \
  4623. !           sys_errlist[errno] : "Unknown error.")
  4624.   
  4625. ! import char *mktemp();
  4626.   
  4627.   static FILE *nntp_in = NULL;        /* fp for reading from server */
  4628.   static FILE *nntp_out = NULL;        /* fp for writing to server */
  4629. ***************
  4630. *** 60,74 ****
  4631.   static int is_connected = 0;        /* bool: t iff we are connected */
  4632.   static group_header *group_hd;        /* ptr to servers current group */
  4633.   static int is_set = 0;            /* bool: t iff group_hd is set */
  4634.   
  4635. ! #define ERROR_LEVEL    400        /* All codes below are not errors */
  4636.   
  4637.   
  4638.   /* 
  4639.    * nntp_find_server: Find out which host to use as NNTP server.
  4640.    *
  4641. !  *     This is done by consulting the file NNTP_SERVER (defined in config.h).
  4642. !  *     Set nntp_server[] to the host's name.
  4643.    */
  4644.   
  4645.   void nntp_find_server()
  4646. --- 55,96 ----
  4647.   static int is_connected = 0;        /* bool: t iff we are connected */
  4648.   static group_header *group_hd;        /* ptr to servers current group */
  4649.   static int is_set = 0;            /* bool: t iff group_hd is set */
  4650. + static int try_again = 0;        /* bool: t if timeout forces retry */
  4651. + static int can_post = 0;        /* bool: t iff NNTP server accepts postings */
  4652. + #define ERR_TIMEOUT    503        /* Response code for timeout */
  4653. + #ifdef DEBUG
  4654. + static FILE *nntp_debug;
  4655.   
  4656. ! /* 
  4657. !  * nntp_debug_msg: print a debug message.
  4658. !  *
  4659. !  *    The master appends prefix and str to a log file, and clients
  4660. !  *    prints it as a message.
  4661. !  */
  4662.   
  4663. + nntp_debug_msg(prefix, str)
  4664. +     char *prefix, *str;
  4665. + {
  4666. +     if (is_master) {
  4667. +     if (nntp_debug != 0) {
  4668. +         fprintf(nntp_debug, "%s %s\n", prefix, str);
  4669. +         fflush(nntp_debug);
  4670. +     }
  4671. +     } else {
  4672. +     msg("%s %s", prefix, str);
  4673. +     fl;
  4674. +     sleep();
  4675. +     }
  4676. + }
  4677. + #endif
  4678.   
  4679.   /* 
  4680.    * nntp_find_server: Find out which host to use as NNTP server.
  4681.    *
  4682. !  *     This is done by consulting the file NNTP_SERVER (defined in
  4683. !  *     config.h).  Set nntp_server[] to the host's name.
  4684.    */
  4685.   
  4686.   void nntp_find_server()
  4687. ***************
  4688. *** 78,86 ****
  4689.       FILE *fp;
  4690.       
  4691.       /* 
  4692. !      * This feature cannot normally be enabled, because the data base
  4693. !      * and the users rc file contains references to articles by number,
  4694. !      * which is not unique across NNTP servers.
  4695.        */
  4696.   #ifdef DEBUG 
  4697.       if ((cp = getenv("NNTPSERVER")) != NULL) {
  4698. --- 100,108 ----
  4699.       FILE *fp;
  4700.       
  4701.       /* 
  4702. !      * This feature cannot normally be enabled, because the database and
  4703. !      * the users rc file contains references to articles by number, and
  4704. !      * these numbers are not unique across NNTP servers.
  4705.        */
  4706.   #ifdef DEBUG 
  4707.       if ((cp = getenv("NNTPSERVER")) != NULL) {
  4708. ***************
  4709. *** 88,98 ****
  4710.       return;
  4711.       }
  4712.   #endif /* DEBUG */
  4713.       name = NNTP_SERVER;
  4714.       if (*name != '/')
  4715.       name = relative(lib_directory, name);
  4716.       if ((fp = open_file(name, OPEN_READ)) != NULL) {
  4717.       while (fgets(buf, sizeof buf, fp) != 0) {
  4718.           if (*buf == '#' || *buf == '\n')
  4719. --- 110,120 ----
  4720.       return;
  4721.       }
  4722.   #endif /* DEBUG */
  4723. !     
  4724.       name = NNTP_SERVER;
  4725.       if (*name != '/')
  4726.       name = relative(lib_directory, name);
  4727. !     
  4728.       if ((fp = open_file(name, OPEN_READ)) != NULL) {
  4729.       while (fgets(buf, sizeof buf, fp) != 0) {
  4730.           if (*buf == '#' || *buf == '\n')
  4731. ***************
  4732. *** 108,114 ****
  4733.       
  4734.       if (!is_master)
  4735.       printf("\nCannot find name of NNTP server.\nCheck %s\n", name);
  4736.       sys_error("Failed to find name of NNTP server!");
  4737.   }
  4738.   
  4739. --- 130,136 ----
  4740.       
  4741.       if (!is_master)
  4742.       printf("\nCannot find name of NNTP server.\nCheck %s\n", name);
  4743. !     
  4744.       sys_error("Failed to find name of NNTP server!");
  4745.   }
  4746.   
  4747. ***************
  4748. *** 124,134 ****
  4749.   {
  4750.       char host[128];
  4751.       char *cp;
  4752.       nntp_find_server();
  4753.       gethostname(host, sizeof host);
  4754.       use_nntp = strcmp(host, nntp_server) != 0; /* too simplistic ??? */
  4755.       if (use_nntp) 
  4756.       strcpy(news_active, relative(db_directory, "ACTIVE"));
  4757.       else 
  4758. --- 146,156 ----
  4759.   {
  4760.       char host[128];
  4761.       char *cp;
  4762. !     
  4763.       nntp_find_server();
  4764.       gethostname(host, sizeof host);
  4765.       use_nntp = strcmp(host, nntp_server) != 0; /* too simplistic ??? */
  4766. !     
  4767.       if (use_nntp) 
  4768.       strcpy(news_active, relative(db_directory, "ACTIVE"));
  4769.       else 
  4770. ***************
  4771. *** 148,165 ****
  4772.       int sockt_rd, sockt_wr;
  4773.       int response;
  4774.       char line[NNTP_STRLEN];
  4775. !     if (!is_master && !silent) {
  4776. !     printf("\rConnecting to NNTP server %s ... ", nntp_server);
  4777. !     fl;
  4778. !     }
  4779.       nntp_failed = 1;
  4780.       is_connected = 0;
  4781.   
  4782.       sockt_rd = nntp_get_socket();
  4783.       if (sockt_rd < 0)
  4784. !       return -1;
  4785.       if ((nntp_in = fdopen(sockt_rd, "r")) == NULL) {
  4786.       close(sockt_rd);
  4787.           return -1;
  4788. --- 170,197 ----
  4789.       int sockt_rd, sockt_wr;
  4790.       int response;
  4791.       char line[NNTP_STRLEN];
  4792. !     
  4793. !     if (!is_master && !silent)
  4794. !     msg("Connecting to NNTP server %s ... ", nntp_server);
  4795. !     
  4796.       nntp_failed = 1;
  4797.       is_connected = 0;
  4798.   
  4799. + #ifdef DEBUG
  4800. +     if (is_master) {
  4801. +     if (nntp_debug != 0) {
  4802. +         fclose(nntp_debug);
  4803. +         rename("/usr/tmp/nnmaster.log", "/usr/tmp/nnmaster.prev");
  4804. +     }
  4805. +     nntp_debug = fopen("/usr/tmp/nnmaster.log", "a");
  4806. +     } else
  4807. +     nntp_debug = 0;
  4808. + #endif
  4809. +     
  4810.       sockt_rd = nntp_get_socket();
  4811.       if (sockt_rd < 0)
  4812. !     return -1;
  4813. !     
  4814.       if ((nntp_in = fdopen(sockt_rd, "r")) == NULL) {
  4815.       close(sockt_rd);
  4816.           return -1;
  4817. ***************
  4818. *** 171,198 ****
  4819.           nntp_in = NULL;               /* from above */
  4820.           return -1;
  4821.       }
  4822.       /* Now get the server's signon message */
  4823.       response = nntp_get_server(line, sizeof(line));
  4824. !     if (response < 0 || response >= ERROR_LEVEL) {
  4825. !     if (!is_master) {
  4826. !         user_error("Failed to connect to NNTP server.\n%s",
  4827. !                 response >= ERROR_LEVEL ? line : syserr());
  4828. !         /* NOTREACHED */
  4829. !     } else {
  4830. !         log_entry('N', "Failed to connect to NNTP server.\n%s",
  4831. !               response >= ERROR_LEVEL ? line : syserr());
  4832.           fclose(nntp_out);
  4833.           fclose(nntp_in);
  4834.           return -1;
  4835.       }
  4836. !     }
  4837. !     if (!is_master && !silent) {
  4838. !     fputs("ok.\r", stdout);
  4839. !     fl;
  4840.       }
  4841.       is_connected = 1;
  4842.       nntp_failed = 0;
  4843.       return 0;
  4844.   }
  4845.   
  4846. --- 203,241 ----
  4847.           nntp_in = NULL;               /* from above */
  4848.           return -1;
  4849.       }
  4850. !     
  4851.       /* Now get the server's signon message */
  4852.       response = nntp_get_server(line, sizeof(line));
  4853. !     
  4854. !     if (is_master) {
  4855. !     if (response != OK_CANPOST && response != OK_NOPOST) {
  4856. !         log_entry('N', "Failed to connect to NNTP server");
  4857. !         log_entry('N', "Response: %s", line);
  4858.           fclose(nntp_out);
  4859.           fclose(nntp_in);
  4860.           return -1;
  4861.       }
  4862. !     } else {
  4863. !     switch (response) {
  4864. !     case OK_CANPOST:
  4865. !         can_post = 1;
  4866. !         break;
  4867. !     case OK_NOPOST:
  4868. !         can_post = 0;
  4869. !         break;
  4870. !     default:
  4871. !         user_error(line);
  4872. !         /* NOTREACHED */
  4873. !     }
  4874.       }
  4875. +     if (!is_master && !silent)
  4876. +     msg("Connecting to NNTP server %s ... ok (%s)",
  4877. +         nntp_server, can_post ? "posting is allowed" : "no posting");
  4878. +     
  4879.       is_connected = 1;
  4880. +     is_set = 0;
  4881.       nntp_failed = 0;
  4882. +     try_again = 0;
  4883.       return 0;
  4884.   }
  4885.   
  4886. ***************
  4887. *** 213,243 ****
  4888.       register char **cp;
  4889.   #endif
  4890.       int (*errfct)() = is_master ? sys_error : user_error;
  4891.       if ((sp = getservbyname("nntp", "tcp")) ==  NULL)
  4892.       (*errfct)("nntp/tcp: Unknown service.\n");
  4893.       if ((hp = gethostbyname(nntp_server)) == NULL)
  4894.       (*errfct)("NNTP server %s unknown.\n", nntp_server);
  4895.       bzero((char *) &sin, sizeof(sin));
  4896.       sin.sin_family = hp->h_addrtype;
  4897.       sin.sin_port = sp->s_port;
  4898.   #ifdef  h_addr
  4899.       /* get a socket and initiate connection -- use multiple addresses */
  4900.       for (cp = hp->h_addr_list; cp && *cp; cp++) {
  4901.       s = socket(hp->h_addrtype, SOCK_STREAM, 0);
  4902.       if (s < 0)
  4903.           (*errfct)("Can't get NNTP socket: %s\n", syserr());
  4904.       bcopy(*cp, (char *)&sin.sin_addr, hp->h_length);
  4905.       x = connect(s, (struct sockaddr *)&sin, sizeof (sin));
  4906.       if (x == 0)
  4907.           break;
  4908.       if (!is_master)
  4909. !         msg("Connecting to %s: %s", nntp_server, syserr());
  4910.       (void) close(s);
  4911.       s = -1;
  4912.       }
  4913. --- 256,286 ----
  4914.       register char **cp;
  4915.   #endif
  4916.       int (*errfct)() = is_master ? sys_error : user_error;
  4917. !     
  4918.       if ((sp = getservbyname("nntp", "tcp")) ==  NULL)
  4919.       (*errfct)("nntp/tcp: Unknown service.\n");
  4920. !     
  4921.       if ((hp = gethostbyname(nntp_server)) == NULL)
  4922.       (*errfct)("NNTP server %s unknown.\n", nntp_server);
  4923. !     
  4924.       bzero((char *) &sin, sizeof(sin));
  4925.       sin.sin_family = hp->h_addrtype;
  4926.       sin.sin_port = sp->s_port;
  4927. !     
  4928.   #ifdef  h_addr
  4929.       /* get a socket and initiate connection -- use multiple addresses */
  4930. !     
  4931.       for (cp = hp->h_addr_list; cp && *cp; cp++) {
  4932.       s = socket(hp->h_addrtype, SOCK_STREAM, 0);
  4933.       if (s < 0)
  4934.           (*errfct)("Can't get NNTP socket: %s\n", syserr());
  4935.       bcopy(*cp, (char *)&sin.sin_addr, hp->h_length);
  4936. !     
  4937.       x = connect(s, (struct sockaddr *)&sin, sizeof (sin));
  4938.       if (x == 0)
  4939.           break;
  4940.       if (!is_master)
  4941. !         msg("Connecting to %s failed: %s", nntp_server, syserr());
  4942.       (void) close(s);
  4943.       s = -1;
  4944.       }
  4945. ***************
  4946. *** 246,260 ****
  4947.   #else                    /* no name server */
  4948.       if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  4949.       (*errfct)("Can't get NNTP socket: %s\n", syserr());
  4950.       /* And then connect */
  4951.       bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
  4952.       if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
  4953.       if (is_master)
  4954. !         (*errfct)("Connecting to %s: %s", nntp_server, syserr());
  4955.       s = -1;
  4956.       }
  4957. -     
  4958.   #endif
  4959.       return s;
  4960.   }
  4961. --- 289,302 ----
  4962.   #else                    /* no name server */
  4963.       if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  4964.       (*errfct)("Can't get NNTP socket: %s\n", syserr());
  4965. !     
  4966.       /* And then connect */
  4967.       bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
  4968.       if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
  4969.       if (is_master)
  4970. !         (*errfct)("Connecting to %s failed: %s", nntp_server, syserr());
  4971.       s = -1;
  4972.       }
  4973.   #endif
  4974.       return s;
  4975.   }
  4976. ***************
  4977. *** 266,279 ****
  4978.    */
  4979.   
  4980.   nntp_put_server(string)
  4981. ! char *string;
  4982.   {
  4983.   #ifdef DEBUG
  4984. !     msg(">>> %s", string);
  4985.   #endif
  4986.       fprintf(nntp_out, "%s\r\n", string);
  4987.       if (fflush(nntp_out) == EOF) {
  4988. !     nntp_error();
  4989.       return -1;
  4990.       }
  4991.       return 0;
  4992. --- 308,321 ----
  4993.    */
  4994.   
  4995.   nntp_put_server(string)
  4996. !     char *string;
  4997.   {
  4998.   #ifdef DEBUG
  4999. !     nntp_debug_msg(">>>", string);
  5000.   #endif
  5001.       fprintf(nntp_out, "%s\r\n", string);
  5002.       if (fflush(nntp_out) == EOF) {
  5003. !     nntp_io_error();
  5004.       return -1;
  5005.       }
  5006.       return 0;
  5007. ***************
  5008. *** 282,299 ****
  5009.   /* 
  5010.    * nntp_get_server_line: get a line from the server.
  5011.    *
  5012. !  *     Expects to be connected to the server.  
  5013. !  *     The line can be any kind of line i.e., either response or text.
  5014.    */
  5015.   
  5016.   nntp_get_server_line(string, size)
  5017. ! char *string;
  5018. ! int size;
  5019.   {
  5020.       register char *cp, *nl;
  5021.       if (fgets(string, size, nntp_in) == NULL) {
  5022. !     nntp_error();
  5023.       return -1;
  5024.       }
  5025.       for (cp = string, nl = NULL; *cp != NUL; cp++) {
  5026. --- 324,341 ----
  5027.   /* 
  5028.    * nntp_get_server_line: get a line from the server.
  5029.    *
  5030. !  *     Expects to be connected to the server.
  5031. !  *     The line can be any kind of line, i.e., either response or text.
  5032.    */
  5033.   
  5034.   nntp_get_server_line(string, size)
  5035. !     char *string;
  5036. !     int size;
  5037.   {
  5038.       register char *cp, *nl;
  5039. !     
  5040.       if (fgets(string, size, nntp_in) == NULL) {
  5041. !     nntp_io_error();
  5042.       return -1;
  5043.       }
  5044.       for (cp = string, nl = NULL; *cp != NUL; cp++) {
  5045. ***************
  5046. *** 305,311 ****
  5047.           nl = cp;
  5048.       }    
  5049.       if (nl != NULL) *nl = NUL;
  5050.       return 0;
  5051.   }
  5052.   
  5053. --- 347,353 ----
  5054.           nl = cp;
  5055.       }    
  5056.       if (nl != NULL) *nl = NUL;
  5057. !     
  5058.       return 0;
  5059.   }
  5060.   
  5061. ***************
  5062. *** 313,331 ****
  5063.    * nntp_get_server: get a response line from the server.
  5064.    *
  5065.    *     Expects to be connected to the server.  
  5066. !  *     The numerical value of the response is returned.
  5067.    */
  5068.   
  5069.   nntp_get_server(string, size)
  5070. ! char *string;
  5071. ! int size;
  5072.   {
  5073.       if (nntp_get_server_line(string, size) < 0)
  5074.       return -1;
  5075.       return isdigit(*string) ? atoi(string) : 0;
  5076.   }
  5077.   
  5078.   /* 
  5079.    * nntp_close_server: close the connection to the server.
  5080.    */
  5081.   
  5082. --- 355,422 ----
  5083.    * nntp_get_server: get a response line from the server.
  5084.    *
  5085.    *     Expects to be connected to the server.  
  5086. !  *     Returns the numerical value of the reponse, or -1 in case of errors.
  5087.    */
  5088.   
  5089.   nntp_get_server(string, size)
  5090. !     char *string;
  5091. !     int size;
  5092.   {
  5093.       if (nntp_get_server_line(string, size) < 0)
  5094.       return -1;
  5095. + #ifdef DEBUG
  5096. +     nntp_debug_msg("<<<", string);
  5097. + #endif
  5098.       return isdigit(*string) ? atoi(string) : 0;
  5099.   }
  5100.   
  5101.   /* 
  5102. +  * nntp_ask_server:  ask the server a question and return the answer.
  5103. +  *
  5104. +  *    Expects to be connected to the server.  
  5105. +  *    Returns the numerical value of the reponse, or -1 in case of
  5106. +  *    errors.
  5107. +  *    Contains some code to handle server timeouts intelligently.
  5108. +  */
  5109. + nntp_ask_server(string, size)
  5110. +     char *string;
  5111. +     int size;
  5112. + {
  5113. +     int response;
  5114. +     if (nntp_put_server(string) < 0)
  5115. +     return -1;
  5116. +     response = nntp_get_server(string, size);
  5117. +     /* 
  5118. +      * Handle the response from the server.  Responses are handled as
  5119. +      * followes:
  5120. +      *
  5121. +      * 100-199    Informational.  Passed back. (should they be ignored?).
  5122. +      * 200-299    Ok messages.  Passed back.
  5123. +      * 300-399    Ok and proceed.  Can not happen in nn.
  5124. +      * 400-499    Errors (no article, etc).  Passed up and handled there.
  5125. +      * 500-599    Fatal NNTP errors.  Handled below.
  5126. +      */
  5127. +     if (response == ERR_GOODBYE || response > ERR_COMMAND) {
  5128. +     nntp_failed = 1;
  5129. +     nntp_close_server();
  5130. +     if (response != ERR_TIMEOUT) {    /* if not timeout, complain */
  5131. +         if (is_master)
  5132. +         sys_error("NNTP botch: internal error: %s", string);
  5133. +         else
  5134. +         user_error("NNTP botch: internal error: %s", string);
  5135. +         /* NOTREACHED */
  5136. +     }
  5137. +     try_again = 1;
  5138. +     is_set = 0;
  5139. +     }
  5140. +     return response;
  5141. + }
  5142. + /* 
  5143.    * nntp_close_server: close the connection to the server.
  5144.    */
  5145.   
  5146. ***************
  5147. *** 333,381 ****
  5148.   {
  5149.       if (!is_connected)
  5150.       return;
  5151.       if (!nntp_failed) {            /* avoid infinite recursion */
  5152.       char line[NNTP_STRLEN];
  5153. !     (void) nntp_put_server("QUIT");
  5154. !     (void) nntp_get_server(line, sizeof line);
  5155.       }
  5156.       (void) fclose(nntp_out);
  5157.       (void) fclose(nntp_in);
  5158.       is_connected = 0;
  5159.   }
  5160.   
  5161.   /* 
  5162. !  * nntp_ask_server:  ask the server a question and return the answer.
  5163. !  *
  5164. !  *    Expects to be connected to the server.  
  5165. !  *    Returns the numerical value of the reponse, or -1 in case of errors.
  5166. !  */
  5167. ! nntp_ask_server(string, size)
  5168. ! char *string;
  5169. ! int size;
  5170. ! {
  5171. !     if (nntp_put_server(string) < 0 || nntp_get_server(string, size) < 0)
  5172. !     return -1;
  5173. ! #ifdef DEBUG
  5174. !     msg("<<< %.75s", string);
  5175. ! #endif
  5176. !     return isdigit(*string) ? atoi(string) : 0;
  5177. ! }
  5178. ! /* 
  5179. !  * nntp_error: signal an error in talking to the server.
  5180.    *
  5181. !  *     An nn client terminates a session with the user.  
  5182. !  *    The master simply closes the connection, which is probably 
  5183. !  *    inadequate.  nntp_failed is set, for use by the master to
  5184. !  *    terminate collection.
  5185.    */
  5186.   
  5187. ! nntp_error()
  5188.   {
  5189.       nntp_failed = 1;
  5190.       if (is_master) {
  5191. --- 424,459 ----
  5192.   {
  5193.       if (!is_connected)
  5194.       return;
  5195. !     
  5196.       if (!nntp_failed) {            /* avoid infinite recursion */
  5197.       char line[NNTP_STRLEN];
  5198. !     int n;
  5199. !     
  5200. !     strcpy(line, "QUIT");
  5201. !     n = nntp_ask_server(line, sizeof line);
  5202. !     if (n != OK_GOODBYE)
  5203. !         ;                /* WHAT NOW ??? */
  5204.       }
  5205. !     
  5206.       (void) fclose(nntp_out);
  5207.       (void) fclose(nntp_in);
  5208. !     
  5209.       is_connected = 0;
  5210.   }
  5211.   
  5212.   /* 
  5213. !  * nntp_io_error: signal an I/O error in talking to the server.
  5214.    *
  5215. !  *     An nn client terminates a session with the user.  The master
  5216. !  *    simply closes the connection.  The flag nntp_failed is set, for
  5217. !  *    use by the master to terminate collection.
  5218. !  *
  5219. !  *    BUG: if the nntp server is forcibly killed, errno can contain a
  5220. !  *    bogus value, resulting in strange error messages.  It is
  5221. !  *    probably better just to write out the numerical value of errno.
  5222.    */
  5223.   
  5224. ! nntp_io_error()
  5225.   {
  5226.       nntp_failed = 1;
  5227.       if (is_master) {
  5228. ***************
  5229. *** 384,397 ****
  5230.           nntp_close_server();
  5231.       }
  5232.       } else {
  5233. ! #ifdef DEBUG
  5234. !     printf("Can't talk to NNTP server %s: %s", nntp_server, syserr());
  5235. !     abort();
  5236. ! #else
  5237. !     user_error("Can't talk to NNTP server %s: %s", nntp_server, syserr());
  5238. ! #endif
  5239.       }
  5240.   }
  5241.   
  5242.   /* 
  5243.    * nntp_copy_text: copy text response into file.
  5244. --- 462,487 ----
  5245.           nntp_close_server();
  5246.       }
  5247.       } else {
  5248. !     user_error("Lost connection to NNTP server %s: %s", nntp_server, syserr());
  5249. !         /* NOTREACHED */
  5250. !     }
  5251. ! }
  5252. ! /* 
  5253. !  * nntp_no_post: Check to see whether posting is allowed.
  5254. !  */
  5255. ! nntp_no_post()
  5256. ! {
  5257. !     if (!is_connected && nntp_server_init() < 0)
  5258. !     return 1;            /* If we cannot connect, neither can inews */
  5259. !     if (can_post == 0) {
  5260. !     msg("NNTP server does not allow postings from this host.  Sorry!");
  5261. !     return 1;
  5262.       }
  5263. +     return 0;
  5264.   }
  5265. +    
  5266.   
  5267.   /* 
  5268.    * nntp_copy_text: copy text response into file.
  5269. ***************
  5270. *** 398,421 ****
  5271.    *
  5272.    *     Sends COMMAND to the server, and copies the following text response
  5273.    *     into an open file.
  5274. !  *    Return -1 on error, 0 otherwise.
  5275.    */
  5276.   
  5277. ! nntp_copy_text(fp, command)
  5278. ! FILE *fp;
  5279. ! char *command;
  5280.   {
  5281.       char buf[NNTP_STRLEN];
  5282.       char *cp;
  5283.       int n, nlines;
  5284.       strcpy(buf, command);
  5285.       if ((n = nntp_ask_server(buf, sizeof buf)) < 0) {
  5286.       return -1;
  5287.       }
  5288. !     if (n >= ERROR_LEVEL)
  5289.       return -1;
  5290.       nlines = 0;
  5291.       while ((n = nntp_get_server_line(buf, sizeof buf)) >= 0) {
  5292.       cp = buf;
  5293. --- 488,513 ----
  5294.    *
  5295.    *     Sends COMMAND to the server, and copies the following text response
  5296.    *     into an open file.
  5297. !  *    Return -1 on error, 0 otherwise.  It is treated as an error, if
  5298. !  *    the returned response it not what was expected.
  5299.    */
  5300.   
  5301. ! nntp_copy_text(fp, command, expected)
  5302. !     FILE *fp;
  5303. !     char *command;
  5304. !     int expected;
  5305.   {
  5306.       char buf[NNTP_STRLEN];
  5307.       char *cp;
  5308.       int n, nlines;
  5309. !     
  5310.       strcpy(buf, command);
  5311.       if ((n = nntp_ask_server(buf, sizeof buf)) < 0) {
  5312.       return -1;
  5313.       }
  5314. !     if (n != expected)
  5315.       return -1;
  5316. !     
  5317.       nlines = 0;
  5318.       while ((n = nntp_get_server_line(buf, sizeof buf)) >= 0) {
  5319.       cp = buf;
  5320. ***************
  5321. *** 447,467 ****
  5322.       char bufo[NNTP_STRLEN], bufn[NNTP_STRLEN];
  5323.       char *new_name;
  5324.       int same;
  5325.       if (!is_master) 
  5326.       return access(news_active, 4);
  5327. -     
  5328. -     if (!is_connected && nntp_server_init() < 0)
  5329. -         return -1;
  5330.   
  5331.       new_name = mktemp(relative(db_directory, ".actXXXXXX"));
  5332.       if ((new = fopen(new_name, "w+")) == NULL)
  5333.       return -1;
  5334. !     if (nntp_copy_text(new, "list") < 0) {
  5335.       fclose(new);
  5336.       unlink(new_name);
  5337. !     return -1;
  5338.       }
  5339.       rewind(new);
  5340.       same = 0;
  5341. --- 539,563 ----
  5342.       char bufo[NNTP_STRLEN], bufn[NNTP_STRLEN];
  5343.       char *new_name;
  5344.       int same;
  5345. !     
  5346.       if (!is_master) 
  5347.       return access(news_active, 4);
  5348.   
  5349. +  again:
  5350. +     if (!is_connected && nntp_server_init() < 0)
  5351. +     return -1;
  5352. +     
  5353.       new_name = mktemp(relative(db_directory, ".actXXXXXX"));
  5354. !     
  5355.       if ((new = fopen(new_name, "w+")) == NULL)
  5356.       return -1;
  5357. !     if (nntp_copy_text(new, "LIST", OK_GROUPS) < 0) {
  5358.       fclose(new);
  5359.       unlink(new_name);
  5360. !     if (try_again)            /* Handle nntp server timeouts */
  5361. !         goto again;
  5362. !     else
  5363. !         return -1;
  5364.       }
  5365.       rewind(new);
  5366.       same = 0;
  5367. ***************
  5368. *** 474,486 ****
  5369.       fclose(old);
  5370.       }
  5371.       fclose(new);
  5372.       if (same) 
  5373.       unlink(new_name);
  5374.       else
  5375.       if (rename(new_name, news_active) != 0)
  5376.           sys_error("Cannot rename %s to %s", new_name, news_active);
  5377.       return 0;
  5378.   }
  5379.   
  5380. --- 570,582 ----
  5381.       fclose(old);
  5382.       }
  5383.       fclose(new);
  5384. !     
  5385.       if (same) 
  5386.       unlink(new_name);
  5387.       else
  5388.       if (rename(new_name, news_active) != 0)
  5389.           sys_error("Cannot rename %s to %s", new_name, news_active);
  5390. !     
  5391.       return 0;
  5392.   }
  5393.   
  5394. ***************
  5395. *** 507,518 ****
  5396.    */
  5397.   
  5398.   struct cache *nntp_search_cache(art, gh)
  5399. ! article_number art;
  5400. ! group_header *gh;
  5401.   {
  5402.       struct cache *cptr = cache;
  5403.       int i;
  5404.       for (i = 0; i < NNTPCACHE; i++, cptr++)
  5405.       if (cptr->art == art && cptr->grp == gh) {
  5406.           cptr->time = cur_time++;
  5407. --- 603,614 ----
  5408.    */
  5409.   
  5410.   struct cache *nntp_search_cache(art, gh)
  5411. !     article_number art;
  5412. !     group_header *gh;
  5413.   {
  5414.       struct cache *cptr = cache;
  5415.       int i;
  5416. !     
  5417.       for (i = 0; i < NNTPCACHE; i++, cptr++)
  5418.       if (cptr->art == art && cptr->grp == gh) {
  5419.           cptr->time = cur_time++;
  5420. ***************
  5421. *** 535,541 ****
  5422.       int i, lru;
  5423.       unsigned min_time = cur_time;
  5424.       char name[24];
  5425. !     
  5426.       for (i = 0; i < NNTPCACHE; i++, cptr++)
  5427.       if (min_time > cptr->time) {
  5428.           min_time = cptr->time;
  5429. --- 631,637 ----
  5430.       int i, lru;
  5431.       unsigned min_time = cur_time;
  5432.       char name[24];
  5433. !     
  5434.       for (i = 0; i < NNTPCACHE; i++, cptr++)
  5435.       if (min_time > cptr->time) {
  5436.           min_time = cptr->time;
  5437. ***************
  5438. *** 542,548 ****
  5439.           lru = i;
  5440.       }
  5441.       cptr = &cache[lru];
  5442.       if (cptr->file_name) {
  5443.       unlink(cptr->file_name);
  5444.       free(cptr->file_name);
  5445. --- 638,644 ----
  5446.           lru = i;
  5447.       }
  5448.       cptr = &cache[lru];
  5449. !     
  5450.       if (cptr->file_name) {
  5451.       unlink(cptr->file_name);
  5452.       free(cptr->file_name);
  5453. ***************
  5454. *** 552,560 ****
  5455.       copy_str(relative(is_master ? lib_directory : nn_directory,
  5456.                 mktemp(name)));
  5457.       cptr->time = cur_time++;
  5458. - #ifdef DEBUG
  5459. -     msg("cache: select slot %d, file name %s", lru, cptr->file_name);
  5460. - #endif
  5461.       return cptr;
  5462.   }
  5463.   
  5464. --- 648,653 ----
  5465. ***************
  5466. *** 568,574 ****
  5467.   {
  5468.       struct cache *cptr = cache;
  5469.       int i;
  5470.       for (i = 0; i < NNTPCACHE; i++, cptr++)
  5471.       if (cptr->file_name)
  5472.           unlink(cptr->file_name);
  5473. --- 661,667 ----
  5474.   {
  5475.       struct cache *cptr = cache;
  5476.       int i;
  5477. !     
  5478.       for (i = 0; i < NNTPCACHE; i++, cptr++)
  5479.       if (cptr->file_name)
  5480.           unlink(cptr->file_name);
  5481. ***************
  5482. *** 582,588 ****
  5483.    */
  5484.   
  5485.   nntp_set_group(gh)
  5486. ! group_header *gh;
  5487.   {
  5488.       group_hd = gh;
  5489.       is_set = 0;
  5490. --- 675,681 ----
  5491.    */
  5492.   
  5493.   nntp_set_group(gh)
  5494. !     group_header *gh;
  5495.   {
  5496.       group_hd = gh;
  5497.       is_set = 0;
  5498. ***************
  5499. *** 599,611 ****
  5500.    */
  5501.   
  5502.   FILE *nntp_get_article(article)
  5503. ! article_number article;
  5504.   {
  5505.       char buf[NNTP_STRLEN];
  5506.       FILE *tmp;
  5507.       struct cache *cptr;
  5508.       int n;
  5509. !     
  5510.       if (!is_connected && nntp_server_init() < 0) {
  5511.       return NULL;
  5512.       }
  5513. --- 692,705 ----
  5514.    */
  5515.   
  5516.   FILE *nntp_get_article(article)
  5517. !     article_number article;
  5518.   {
  5519.       char buf[NNTP_STRLEN];
  5520.       FILE *tmp;
  5521.       struct cache *cptr;
  5522.       int n;
  5523. !  again:
  5524.       if (!is_connected && nntp_server_init() < 0) {
  5525.       return NULL;
  5526.       }
  5527. ***************
  5528. *** 614,629 ****
  5529.        * Set the server group to the current group
  5530.        */
  5531.       if (is_set == 0) {
  5532. !     sprintf(buf, "group %s", group_hd->group_name);
  5533. !     if ((n = nntp_ask_server(buf, sizeof buf)) < 0){
  5534.           return NULL;
  5535.       }
  5536. !     if (n >= ERROR_LEVEL)
  5537. !         return NULL;
  5538.       is_set = 1;
  5539.       }
  5540.       /* 
  5541. !      * Search the cache for the requested article,and allocate a new
  5542.        * slot if necessary.
  5543.        */
  5544.       cptr = nntp_search_cache(article, group_hd);
  5545. --- 708,727 ----
  5546.        * Set the server group to the current group
  5547.        */
  5548.       if (is_set == 0) {
  5549. !     sprintf(buf, "GROUP %s", group_hd->group_name);
  5550. !     if ((n = nntp_ask_server(buf, sizeof buf)) < 0) {
  5551.           return NULL;
  5552.       }
  5553. !     if (n != OK_GROUP) {
  5554. !         if (try_again)
  5555. !         goto again;        /* Handle nntp server timeouts */
  5556. !         else
  5557. !         return NULL;
  5558. !     }
  5559.       is_set = 1;
  5560.       }
  5561.       /* 
  5562. !      * Search the cache for the requested article, and allocate a new
  5563.        * slot if necessary.
  5564.        */
  5565.       cptr = nntp_search_cache(article, group_hd);
  5566. ***************
  5567. *** 631,647 ****
  5568.       return open_file(cptr->file_name, OPEN_READ);
  5569.       } 
  5570.       cptr = nntp_new_slot();
  5571.       if ((tmp = open_file(cptr->file_name, OPEN_CREATE)) == NULL)
  5572.       return NULL;
  5573.       /* 
  5574.        * Copy the article.
  5575.        */
  5576. !     sprintf(buf, "article %d", article);
  5577. !     if (nntp_copy_text(tmp, buf) < 0) {
  5578.       fclose(tmp);
  5579. !     return NULL;
  5580.       }
  5581.       fclose(tmp);
  5582.       if ((tmp = open_file(cptr->file_name, OPEN_READ)) != NULL) {
  5583. --- 729,748 ----
  5584.       return open_file(cptr->file_name, OPEN_READ);
  5585.       } 
  5586.       cptr = nntp_new_slot();
  5587. !     
  5588.       if ((tmp = open_file(cptr->file_name, OPEN_CREATE)) == NULL)
  5589.       return NULL;
  5590. !     
  5591.       /* 
  5592.        * Copy the article.
  5593.        */
  5594. !     sprintf(buf, "ARTICLE %d", article);
  5595. !     if (nntp_copy_text(tmp, buf, OK_ARTICLE) < 0) {
  5596.       fclose(tmp);
  5597. !     if (try_again)
  5598. !         goto again;            /* Handle nntp server timeouts */
  5599. !     else
  5600. !         return NULL;
  5601.       }
  5602.       fclose(tmp);
  5603.       if ((tmp = open_file(cptr->file_name, OPEN_READ)) != NULL) {
  5604. *** /usr/storm/nn6.3.2/nnusage.sh    Wed Jun 28 20:08:06 1989
  5605. --- nnusage.sh    Fri Sep  8 12:46:52 1989
  5606. ***************
  5607. *** 1,7 ****
  5608.   # CONFIG file is inserted here
  5609.   
  5610.   if [ x"$1" = x'-t' ] ; then
  5611. !     SORTMODE="+1r"
  5612.   else
  5613.       SORTMODE=""
  5614.   fi
  5615. --- 1,7 ----
  5616.   # CONFIG file is inserted here
  5617.   
  5618.   if [ x"$1" = x'-t' ] ; then
  5619. !     SORTMODE="+1nr"
  5620.   else
  5621.       SORTMODE=""
  5622.   fi
  5623. *** /usr/storm/nn6.3.6/pack_name.c    Mon Sep 18 17:00:48 1989
  5624. --- pack_name.c    Fri Sep  8 12:46:52 1989
  5625. ***************
  5626. *** 183,189 ****
  5627.       return 0;
  5628.   
  5629.       p = source, q = namebuf, n = 0;
  5630. -     maxq = namebuf + sizeof namebuf - 1;
  5631.       
  5632.   new_partition:
  5633.       for (i = SEP_MAXIMUM; --i >= 0; separator[i] = NULL);
  5634. --- 183,188 ----
  5635. ***************
  5636. *** 212,218 ****
  5637.           continue;
  5638.       }
  5639.       if (n > 1) continue;
  5640. -     if (q >= maxq) break;
  5641.       *q++ = c;
  5642.       if (IS_SEPARATOR(c)) {
  5643.           switch (sep = (Class[c] & 0xff)) {
  5644. --- 211,216 ----
  5645. *** /usr/storm/nn6.3.6/patchlevel.h    Mon Sep 18 17:16:13 1989
  5646. --- patchlevel.h    Fri Sep  8 12:46:52 1989
  5647. ***************
  5648. *** 13,20 ****
  5649.    *    1989-06-30:  Patch 3: several files
  5650.    *    1989-07-10:  Patch 4: several files
  5651.    *    1989-08-22:  Patch 5: db.c
  5652. !  *    1989-08-25:  Patch 6: admin.c pack_date.c pack_name.c ...
  5653.    */
  5654.   
  5655. ! #define PATCHLEVEL 6
  5656.   
  5657. --- 13,21 ----
  5658.    *    1989-06-30:  Patch 3: several files
  5659.    *    1989-07-10:  Patch 4: several files
  5660.    *    1989-08-22:  Patch 5: db.c
  5661. !  *    1989-08-25:  Patch 6: admin.c pack_date.c
  5662. !  *    1989-09-08:  Patch 7: several files
  5663.    */
  5664.   
  5665. ! #define PATCHLEVEL 7
  5666.   
  5667. *** /usr/storm/nn6.3.6/rc.c    Mon Sep 18 17:03:22 1989
  5668. --- rc.c    Fri Sep  8 12:46:54 1989
  5669. ***************
  5670. *** 187,193 ****
  5671.   
  5672.       gh->last_article = LASTART(line);
  5673.   
  5674. !     if (gh->group_flag & G_BLOCKED) {
  5675.           /* We cannot trust this group, so we leave it alone */
  5676.           /* group_menu after update_group will do what is necessary */
  5677.           continue;
  5678. --- 187,193 ----
  5679.   
  5680.       gh->last_article = LASTART(line);
  5681.   
  5682. !     if (gh->group_flag & (G_BLOCKED | G_NO_DIRECTORY)) {
  5683.           /* We cannot trust this group, so we leave it alone */
  5684.           /* group_menu after update_group will do what is necessary */
  5685.           continue;
  5686. ***************
  5687. *** 367,376 ****
  5688.       unread_articles = 0;
  5689.       unread_groups = 0;
  5690.       
  5691. !     Loop_Groups_Header(gh) {
  5692.       gh->group_flag &= ~G_UNREAD_COUNT;
  5693.   
  5694.       if ((gh->group_flag & G_SUBSCRIPTION) == 0) continue;
  5695.   
  5696.       if (gh->last_l_article > gh->last_article) {
  5697.           n = unread_articles;
  5698. --- 367,377 ----
  5699.       unread_articles = 0;
  5700.       unread_groups = 0;
  5701.       
  5702. !     Loop_Groups_Sequence(gh) {
  5703.       gh->group_flag &= ~G_UNREAD_COUNT;
  5704.   
  5705.       if ((gh->group_flag & G_SUBSCRIPTION) == 0) continue;
  5706. +     if (gh->group_flag & G_NO_DIRECTORY) continue;
  5707.   
  5708.       if (gh->last_l_article > gh->last_article) {
  5709.           n = unread_articles;
  5710. *** /usr/storm/nn6.3.4/s-aux1-1.h    Mon Jul 10 14:47:39 1989
  5711. --- s-aux1-1.h    Fri Sep  8 12:46:56 1989
  5712. ***************
  5713. *** 94,99 ****
  5714. --- 94,106 ----
  5715.   #define    HAVE_UNAME            /* System V */
  5716.   
  5717.   /*
  5718. +  *    Define HAVE_MULTIGROUP if system has simultaneous multiple group
  5719. +  *    membership capability (BSD style).
  5720. +  */
  5721. + #define HAVE_MULTIGROUP
  5722. + /*
  5723.    *    Define DETATCH_TERMINAL to be a command sequence which 
  5724.    *    will detatch a process from the control terminal
  5725.    *    Also include files needed to perform this HERE.
  5726. *** /usr/storm/nn6.3.0/s-bsd4-2.h    Thu Jun  1 11:11:01 1989
  5727. --- s-bsd4-2.h    Fri Sep  8 12:46:56 1989
  5728. ***************
  5729. *** 90,95 ****
  5730. --- 90,102 ----
  5731.   #define    HAVE_GETHOSTNAME    /* BSD systems */
  5732.   
  5733.   /*
  5734. +  *    Define HAVE_MULTIGROUP if system has simultaneous multiple group
  5735. +  *    membership capability (BSD style).
  5736. +  */
  5737. + #define HAVE_MULTIGROUP
  5738. + /*
  5739.    *    Define DETATCH_TERMINAL to be a command sequence which 
  5740.    *    will detatch a process from the control terminal
  5741.    *    Also include system files needed to perform this HERE.
  5742. *** /usr/storm/nn6.3.0/s-bsd4-3.h    Thu Jun  1 11:11:01 1989
  5743. --- s-bsd4-3.h    Fri Sep  8 12:46:56 1989
  5744. ***************
  5745. *** 96,101 ****
  5746. --- 96,114 ----
  5747.   #define    HAVE_GETHOSTNAME    /* BSD systems */
  5748.   
  5749.   /*
  5750. +  *    Define HAVE_MULTIGROUP if system has simultaneous multiple group
  5751. +  *    membership capability (BSD style).
  5752. +  *
  5753. +  *    Also define GIDSET_TYPE to the type of the elements in the array
  5754. +  *    initialized by getgroups() if different from "int" (many systems 
  5755. +  *    have a gid_t, but very few use it for getgroups()).
  5756. +  */
  5757. + #define HAVE_MULTIGROUP
  5758. + /* #define GIDSET_TYPE    gid_t    /* Newer 4.3 systems may use this */
  5759. + /*
  5760.    *    Define DETATCH_TERMINAL to be a command sequence which 
  5761.    *    will detatch a process from the control terminal
  5762.    *    Also include system files needed to perform this HERE.
  5763. *** /usr/storm/nn6.3.0/s-sunos3.h    Thu Jun  1 11:11:01 1989
  5764. --- s-sunos3.h    Fri Sep  8 12:46:58 1989
  5765. ***************
  5766. *** 97,102 ****
  5767. --- 97,109 ----
  5768.   #define    HAVE_GETHOSTNAME    /* BSD systems */
  5769.   
  5770.   /*
  5771. +  *    Define HAVE_MULTIGROUP if system has simultaneous multiple group
  5772. +  *    membership capability (BSD style).
  5773. +  */
  5774. + #define HAVE_MULTIGROUP
  5775. + /*
  5776.    *    Define DETATCH_TERMINAL to be a command sequence which 
  5777.    *    will detatch a process from the control terminal
  5778.    *    Also include system files needed to perform this HERE.
  5779. *** /usr/storm/nn6.3.0/s-sunos4-0.h    Thu Jun  1 11:11:01 1989
  5780. --- s-sunos4-0.h    Fri Sep  8 12:46:58 1989
  5781. ***************
  5782. *** 97,102 ****
  5783. --- 97,109 ----
  5784.   #define    HAVE_GETHOSTNAME    /* BSD systems */
  5785.   
  5786.   /*
  5787. +  *    Define HAVE_MULTIGROUP if system has simultaneous multiple group
  5788. +  *    membership capability (BSD style).
  5789. +  */
  5790. + #define HAVE_MULTIGROUP
  5791. + /*
  5792.    *    Define DETATCH_TERMINAL to be a command sequence which 
  5793.    *    will detatch a process from the control terminal
  5794.    *    Also include system files needed to perform this HERE.
  5795. *** /usr/storm/nn6.3.2/s-template.h    Wed Jun 28 20:08:08 1989
  5796. --- s-template.h    Fri Sep  8 12:46:58 1989
  5797. ***************
  5798. *** 110,115 ****
  5799. --- 110,127 ----
  5800.   #define    HAVE_UNAME            /* System V */
  5801.   
  5802.   /*
  5803. +  *    Define HAVE_MULTIGROUP if system has simultaneous multiple group
  5804. +  *    membership capability (BSD style).
  5805. +  *    Also define NGROUPS or include the proper .h file if NGROUPS is
  5806. +  *    not defined in <sys/param.h>.
  5807. +  *    Also define GIDSET_TYPE to the type of the elements in the array
  5808. +  *    initialized by getgroups() if different from "int" (many systems 
  5809. +  *    have a gid_t, but very few use it for getgroups()).
  5810. +  */
  5811. + /* #define HAVE_MULTIGROUP    /* BSD */
  5812. + /*
  5813.    *    Define DETATCH_TERMINAL to be a command sequence which 
  5814.    *    will detatch a process from the control terminal
  5815.    *    Also include system files needed to perform this HERE.
  5816. *** /usr/storm/nn6.3.4/s-xenix386.h    Mon Jul 10 14:47:40 1989
  5817. --- s-xenix386.h    Fri Sep  8 12:46:58 1989
  5818. ***************
  5819. *** 124,129 ****
  5820. --- 124,138 ----
  5821.   #define SHELL        "/bin/sh"
  5822.   
  5823.   /*
  5824. +  *    Define AVOID_SHELL_EXEC if the system gets confused by
  5825. +  *        #!/bin/sh
  5826. +  *    lines in shell scripts, e.g. only reads #! and thinks it
  5827. +  *    is a csh script.
  5828. +  */
  5829. + #define AVOID_SHELL_EXEC        /* */
  5830. + /*
  5831.    *    Specify the default mailer to be invoked by nnmail
  5832.    */
  5833.   
  5834. *** /usr/storm/nn6.3.4/save.c    Mon Jul 10 13:36:29 1989
  5835. --- save.c    Fri Sep  8 12:46:59 1989
  5836. ***************
  5837. *** 12,18 ****
  5838. --- 12,20 ----
  5839.   /* #define PAGED_OUTPUT        /* does not work yet!! */
  5840.   
  5841.   export char *default_save_file = "+$F";
  5842. + export char *unshar_header_file = "Unshar.Headers";
  5843.   export int  use_mail_folders = 0;
  5844. + export int  use_mmdf_folders = 0;
  5845.   export int  save_report = 1;
  5846.   export int  quick_save = 0;
  5847.   export int  conf_append = 0;
  5848. ***************
  5849. *** 307,314 ****
  5850.       if (save_mode & UNIQUE_FILES) {
  5851.       do {
  5852.           uniq_counter++;
  5853. !         sprintf(save_name + counter_index, 
  5854. !             save_counter_format, uniq_counter);
  5855.       } while (file_exist(save_name, (char *)NULL));
  5856.   
  5857.       save_mode |= FILE_IS_NEW;
  5858. --- 309,321 ----
  5859.       if (save_mode & UNIQUE_FILES) {
  5860.       do {
  5861.           uniq_counter++;
  5862. !         sprintf(copybuf, save_counter_format, uniq_counter);
  5863. !         if (strcmp(save_name + counter_index, copybuf) == 0) {
  5864. !         msg("save-counter \"%s\" does not generate unique file names",
  5865. !             save_counter_format);
  5866. !         goto fatal;
  5867. !         }
  5868. !         strcpy(save_name + counter_index, copybuf);
  5869.       } while (file_exist(save_name, (char *)NULL));
  5870.   
  5871.       save_mode |= FILE_IS_NEW;
  5872. ***************
  5873. *** 316,335 ****
  5874.       if (save_mode & APPEND_ARTNUM)
  5875.           sprintf(save_name + counter_index, "%d", ah->a_number);
  5876.           
  5877. !     if (save_mode & FILE_IS_NEW) 
  5878.       if (save_mode & IS_PIPE) {
  5879.           if ((save_file = popen(save_name, "w")) == NULL) {
  5880.           msg("Cannot pipe to %s", save_name);
  5881. !         fclose(art);
  5882. !         return 0;
  5883.           }
  5884.       } else
  5885.       if (save_mode & DO_UNSHAR) {
  5886. !         if ((save_mode & DO_PATCH) == 0 && !unshar_position(art)) {
  5887. !         fclose(art);
  5888. !         return 0;
  5889.           }
  5890. !         was_raw = unset_raw();
  5891.           if (save_name) 
  5892.   #ifdef PAGED_OUTPUT
  5893.           sprintf(copybuf, "cd %s && %s %s", save_name, unshar_cmd, pager_redir);
  5894. --- 323,346 ----
  5895.       if (save_mode & APPEND_ARTNUM)
  5896.           sprintf(save_name + counter_index, "%d", ah->a_number);
  5897.           
  5898. !     if (save_mode & FILE_IS_NEW) {
  5899. !     if (save_mode & (IS_PIPE | DO_UNSHAR))
  5900. !         was_raw = unset_raw();
  5901.       if (save_mode & IS_PIPE) {
  5902.           if ((save_file = popen(save_name, "w")) == NULL) {
  5903.           msg("Cannot pipe to %s", save_name);
  5904. !         goto fatal;
  5905.           }
  5906.       } else
  5907.       if (save_mode & DO_UNSHAR) {
  5908. !         if ((save_mode & DO_PATCH) == 0) {
  5909. !         if (!unshar_position(art)) 
  5910. !             goto fatal;
  5911. !         if (unshar_header_file)
  5912. !             store_header(ah, art, save_name, unshar_header_file);
  5913.           }
  5914.           if (save_name) 
  5915.   #ifdef PAGED_OUTPUT
  5916.           sprintf(copybuf, "cd %s && %s %s", save_name, unshar_cmd, pager_redir);
  5917. ***************
  5918. *** 346,354 ****
  5919.           save_file = popen(copybuf, "w");
  5920.           if (save_file == NULL) {
  5921.           msg("Cannot exec: '%s'", copybuf);
  5922. !         if (was_raw) raw();
  5923. !         fclose(art);
  5924. !         return 0;
  5925.           }
  5926.   #ifdef PAGED_OUTPUT
  5927.           fprintf(pager_stream, "\r\n%s %s\r\n", 
  5928. --- 357,363 ----
  5929.           save_file = popen(copybuf, "w");
  5930.           if (save_file == NULL) {
  5931.           msg("Cannot exec: '%s'", copybuf);
  5932. !         goto fatal;
  5933.           }
  5934.   #ifdef PAGED_OUTPUT
  5935.           fprintf(pager_stream, "\r\n%s %s\r\n", 
  5936. ***************
  5937. *** 369,386 ****
  5938.           if (ftell(save_file) != (off_t)0)
  5939.           save_mode &= ~FILE_IS_NEW;
  5940.       }
  5941.       
  5942.       clrline();
  5943.       s_pipe = 0;
  5944.   
  5945. !     if (use_mail_folders && mode != NO_HEADER) {
  5946. !     time_t now;
  5947. !     char *ctime();
  5948. !     
  5949. !     time(&now);
  5950. !     fprintf(save_file, "From %s %s", 
  5951. !         current_group->group_name, ctime(&now));
  5952. !     }
  5953.   
  5954.       if (mode == FULL_HEADER) {
  5955.       off_t cnt = ah->fpos - ah->hpos;
  5956. --- 378,390 ----
  5957.           if (ftell(save_file) != (off_t)0)
  5958.           save_mode &= ~FILE_IS_NEW;
  5959.       }
  5960. +     }
  5961.       
  5962.       clrline();
  5963.       s_pipe = 0;
  5964.   
  5965. !     if (mode != NO_HEADER)
  5966. !     mailbox_format(save_file, 1);
  5967.   
  5968.       if (mode == FULL_HEADER) {
  5969.       off_t cnt = ah->fpos - ah->hpos;
  5970. ***************
  5971. *** 422,432 ****
  5972.       if (s_pipe) goto broken_pipe;
  5973.       }
  5974.       
  5975. !     if (mode) {
  5976. !     putc(NL, save_file);
  5977. !     lcount++;
  5978. !     }
  5979.   broken_pipe:    
  5980.       fclose(art);
  5981.   
  5982. --- 426,434 ----
  5983.       if (s_pipe) goto broken_pipe;
  5984.       }
  5985.       
  5986. !     if (mode != NO_HEADER) 
  5987. !     lcount += mailbox_format(save_file, 0);
  5988. !     
  5989.   broken_pipe:    
  5990.       fclose(art);
  5991.   
  5992. ***************
  5993. *** 459,464 ****
  5994. --- 461,471 ----
  5995.       ah->flag |= A_ST_FILED;
  5996.       
  5997.       return !s_pipe || (save_mode & SEPARATE_FILES);
  5998. +  fatal:
  5999. +     if (was_raw) raw();
  6000. +     fclose(art);
  6001. +     return 0;
  6002.   }
  6003.   
  6004.   
  6005. ***************
  6006. *** 491,496 ****
  6007. --- 498,556 ----
  6008.   #endif
  6009.   }
  6010.   
  6011. + store_header(ah, f, dir, file)
  6012. + article_header *ah;
  6013. + FILE *f;
  6014. + char *dir, *file;
  6015. + {
  6016. +     register int c;
  6017. +     off_t endpos;
  6018. +     FILE *h;
  6019. +     
  6020. +     if (dir != (char *)NULL && file[0] != '/')
  6021. +     file = relative(dir, file);
  6022. +     if ((h = open_file(file, OPEN_APPEND)) == NULL) {
  6023. +     msg("Cannot open %s", file);
  6024. +     return;
  6025. +     }
  6026. +     fseek(h, (off_t)0, 2);
  6027. +     if (!use_mmdf_folders && ftell(h) > 0) putc(NL, h);  /* just in case */
  6028. +     mailbox_format(f, 1);
  6029. +     endpos = ftell(f);
  6030. +     fseek(f, ah->hpos, 0);
  6031. +     while (--endpos >= 0 && (c = getc(f)) != EOF) 
  6032. +     putc(c, h);
  6033. +     
  6034. +     mailbox_format(h, 0);
  6035. +     fclose(h);
  6036. + }
  6037. + mailbox_format(f, top)
  6038. + FILE *f;
  6039. + int top;
  6040. + {
  6041. +     time_t now;
  6042. +     char *ctime();
  6043. +     if (use_mmdf_folders) {
  6044. +     fprintf(f, "\001\001\001\001\n");
  6045. +     return 0;
  6046. +     }
  6047. +     
  6048. +     if (top == 0) {
  6049. +     fputc(NL, f);
  6050. +     return 1;
  6051. +     }
  6052. +     
  6053. +     if (use_mail_folders) {
  6054. +     time(&now);
  6055. +     fprintf(f, "From %s %s", 
  6056. +         current_group->group_name, ctime(&now));
  6057. +     return 1;
  6058. +     }
  6059. +     return 0;
  6060. + }
  6061.   
  6062.   char *run_mkdir(dir, name_buf)
  6063.   char *dir, *name_buf;
  6064. *** /usr/storm/nn6.3.4/selection.c    Mon Jul 10 13:36:30 1989
  6065. --- selection.c    Fri Sep  8 12:46:59 1989
  6066. ***************
  6067. *** 3,8 ****
  6068. --- 3,9 ----
  6069.    */
  6070.   
  6071.   #include "config.h"
  6072. + #include "term.h"
  6073.   #include "articles.h"
  6074.   
  6075.   #define    SLMAGIC    0x536c6375
  6076. *** /usr/storm/nn6.3.6/sequence.c    Mon Sep 18 17:04:11 1989
  6077. --- sequence.c    Fri Sep  8 12:46:59 1989
  6078. ***************
  6079. *** 8,13 ****
  6080. --- 8,14 ----
  6081.   export group_header *group_sequence;
  6082.   export char *read_mail = NULL;
  6083.   export int also_unsub_groups = 0;
  6084. + export int also_subgroups = 1;
  6085.   
  6086.   static int seq_break_enabled = 1;    /* !! enabled */
  6087.   
  6088. ***************
  6089. *** 40,45 ****
  6090. --- 41,47 ----
  6091.       int found, any, errors;
  6092.   
  6093.       group_sequence = NULL;
  6094. +     also_subgroups = 0;
  6095.       
  6096.       any = errors = 0;
  6097.       while (group = *groups++) {
  6098. ***************
  6099. *** 141,147 ****
  6100.   static end_sequence()
  6101.   {
  6102.       register group_header *gh, *backp;
  6103.       if (tail_sequence)
  6104.       tail_sequence->next_group = NULL;
  6105.       
  6106. --- 143,150 ----
  6107.   static end_sequence()
  6108.   {
  6109.       register group_header *gh, *backp;
  6110. !     register int seq_ix;
  6111. !     
  6112.       if (tail_sequence)
  6113.       tail_sequence->next_group = NULL;
  6114.       
  6115. ***************
  6116. *** 149,155 ****
  6117. --- 152,160 ----
  6118.   
  6119.       backp = NULL;
  6120.       gh = group_sequence; 
  6121. +     seq_ix = 0;
  6122.       while (gh) {
  6123. +     gh->preseq_index = ++seq_ix;
  6124.       gh->prev_group = backp;
  6125.       backp = gh;
  6126.       gh = gh->next_group;
  6127. ***************
  6128. *** 204,210 ****
  6129.       register group_header *gh;
  6130.       group_header *get_group_search();
  6131.       char group[FILENAME];
  6132. !     char savefile[FILENAME], *dflt_save;
  6133.       register char *gp;
  6134.       int mode;
  6135.       
  6136. --- 209,216 ----
  6137.       register group_header *gh;
  6138.       group_header *get_group_search();
  6139.       char group[FILENAME];
  6140. !     char savefile[FILENAME], *dflt_save, *enter_macro;
  6141. !     extern char *parse_enter_macro();
  6142.       register char *gp;
  6143.       int mode;
  6144.       
  6145. ***************
  6146. *** 290,307 ****
  6147.           } while (c != EOF && isascii(c) && !isspace(c));
  6148.           *gp = NUL;
  6149.           dflt_save = savefile[0] ? copy_str(savefile) : NULL;
  6150. !     } else {
  6151.           dflt_save = NULL;
  6152.           if (c != EOF) ungetc(c, sf);
  6153.       }
  6154.       
  6155. -      use_same_savefile:    
  6156.       start_group_search(group);
  6157.       
  6158.       while (gh = get_group_search()) {
  6159.   
  6160.           gh->save_file = dflt_save;
  6161.           
  6162.           if (group_name_args == 0 &&
  6163.           (gh->group_flag & G_SUBSCRIPTION) == 0 && !also_unsub_groups)
  6164. --- 296,319 ----
  6165.           } while (c != EOF && isascii(c) && !isspace(c));
  6166.           *gp = NUL;
  6167.           dflt_save = savefile[0] ? copy_str(savefile) : NULL;
  6168. !     } else
  6169.           dflt_save = NULL;
  6170. +      use_same_savefile:    
  6171. +     while (c != EOF && (!isascii(c) || isspace(c))) c = getc(sf);
  6172. +     if (c == '(') {
  6173. +         enter_macro = parse_enter_macro(sf, getc(sf));
  6174. +     } else {
  6175. +         enter_macro = NULL;
  6176.           if (c != EOF) ungetc(c, sf);
  6177.       }
  6178.       
  6179.       start_group_search(group);
  6180.       
  6181.       while (gh = get_group_search()) {
  6182.   
  6183.           gh->save_file = dflt_save;
  6184. +         gh->enter_macro = enter_macro;
  6185.           
  6186.           if (group_name_args == 0 &&
  6187.           (gh->group_flag & G_SUBSCRIPTION) == 0 && !also_unsub_groups)
  6188. ***************
  6189. *** 383,388 ****
  6190. --- 395,401 ----
  6191.   
  6192.   static char *gs_group;
  6193.   static int gs_length, gs_index, gs_mode;
  6194. + static group_header *gs_only_group = NULL;
  6195.   
  6196.   #define    GS_PREFIX    1    /* group. */
  6197.   #define    GS_SUFFIX    2    /* .group */
  6198. ***************
  6199. *** 394,400 ****
  6200.   char *group;
  6201.   {
  6202.       char *dot;
  6203. !     
  6204.       if (strcmp(group, "NEW") == 0) {
  6205.       gs_mode = GS_NEW_GROUP;
  6206.       gs_length = 0;
  6207. --- 407,422 ----
  6208.   char *group;
  6209.   {
  6210.       char *dot;
  6211. !     int last;
  6212. !     
  6213. !     gs_index = master.number_of_groups;
  6214. !     if ((last = strlen(group) - 1) < 0) return;
  6215. !     if (group[last] == '*')
  6216. !     group[last] = NUL;
  6217. !     else
  6218. !     if (!also_subgroups && (gs_only_group = lookup(group)) != NULL)
  6219. !         return;
  6220. !     
  6221.       if (strcmp(group, "NEW") == 0) {
  6222.       gs_mode = GS_NEW_GROUP;
  6223.       gs_length = 0;
  6224. ***************
  6225. *** 430,438 ****
  6226.       register group_header *gh;
  6227.       register int c, tail;
  6228.       
  6229.       while (gs_index < master.number_of_groups) {
  6230.       gh = sorted_groups[gs_index++];
  6231. !     if (gh->group_flag & G_DONE) continue;
  6232.   
  6233.       gs_more_groups++;
  6234.   
  6235. --- 452,468 ----
  6236.       register group_header *gh;
  6237.       register int c, tail;
  6238.       
  6239. +     if (gs_only_group != NULL) {
  6240. +     gh = gs_only_group;
  6241. +     gs_only_group = NULL;
  6242. +     if (gh->group_flag & (G_DONE | G_NO_DIRECTORY)) return NULL;
  6243. +     gh->group_flag |= G_DONE;
  6244. +     return gh;
  6245. +     }
  6246. +     
  6247.       while (gs_index < master.number_of_groups) {
  6248.       gh = sorted_groups[gs_index++];
  6249. !     if (gh->group_flag & (G_DONE | G_NO_DIRECTORY)) continue;
  6250.   
  6251.       gs_more_groups++;
  6252.   
  6253. *** /usr/storm/nn6.3.4/term.c    Mon Jul 10 13:36:32 1989
  6254. --- term.c    Fri Sep  8 12:46:59 1989
  6255. ***************
  6256. *** 18,33 ****
  6257.   export int  show_current_time = 1;
  6258.   export int  conf_dont_sleep = 0;
  6259.   export int  prompt_length;
  6260. ! export int  slow_mode = 0;
  6261.   export int  any_message = 0;
  6262.   export int  flow_control = 1;
  6263.   
  6264. ! export char help_key = '?';
  6265. ! export char comp1_key = SP;
  6266. ! export char comp2_key = TAB;
  6267. ! export char erase_key, kill_key;
  6268. ! export char delword_key = CTRL('W');
  6269.   
  6270.   #ifdef USE_TERMINFO
  6271.   
  6272.   #include <curses.h>
  6273. --- 18,37 ----
  6274.   export int  show_current_time = 1;
  6275.   export int  conf_dont_sleep = 0;
  6276.   export int  prompt_length;
  6277. ! export int  terminal_speed;
  6278. ! export int  slow_speed = 1200;
  6279.   export int  any_message = 0;
  6280.   export int  flow_control = 1;
  6281. + export int  use_visible_bell = 1; /* if supported by terminal */
  6282.   
  6283. ! export unsigned char help_key = '?';
  6284. ! export unsigned char comp1_key = SP;
  6285. ! export unsigned char comp2_key = TAB;
  6286. ! export unsigned char erase_key, kill_key;
  6287. ! export unsigned char delword_key = CONTROL_('W');
  6288.   
  6289. + static char bell_str[256] = "\007";
  6290.   #ifdef USE_TERMINFO
  6291.   
  6292.   #include <curses.h>
  6293. ***************
  6294. *** 49,54 ****
  6295. --- 53,59 ----
  6296.   short ospeed;
  6297.   
  6298.   static char XBC[64], XUP[64];
  6299. + static char enter_ca_mode[64], exit_ca_mode[64];
  6300.   static char cursor_home[64];
  6301.   static char cursor_address[64];
  6302.   static char clear_screen[64];
  6303. ***************
  6304. *** 56,62 ****
  6305.   static char clr_eos[64];
  6306.   static char enter_standout_mode[64], exit_standout_mode[64];
  6307.   static char enter_underline_mode[64], exit_underline_mode[64];
  6308. - static char bell[256];
  6309.   static char key_down[64], key_up[64], key_right[64], key_left[64];
  6310.   
  6311.   int  magic_cookie_glitch;    /* magic cookie size */
  6312. --- 61,66 ----
  6313. ***************
  6314. *** 86,97 ****
  6315.   #include <termio.h>
  6316.   #endif
  6317.   
  6318.   static struct termio norm_tty, raw_tty;
  6319.   
  6320.   #define    IntrC    norm_tty.c_cc[VINTR]
  6321.   #define    EraseC    norm_tty.c_cc[VERASE]
  6322.   #define KillC    norm_tty.c_cc[VKILL]
  6323. ! #define SuspC    CTRL('Z')    /* norm_tty.c_cc[SWTCH] */
  6324.   
  6325.   #else    /* V7/BSD TTY DRIVER */
  6326.   
  6327. --- 90,103 ----
  6328.   #include <termio.h>
  6329.   #endif
  6330.   
  6331. + #undef CBREAK
  6332.   static struct termio norm_tty, raw_tty;
  6333.   
  6334.   #define    IntrC    norm_tty.c_cc[VINTR]
  6335.   #define    EraseC    norm_tty.c_cc[VERASE]
  6336.   #define KillC    norm_tty.c_cc[VKILL]
  6337. ! #define SuspC    CONTROL_('Z')    /* norm_tty.c_cc[SWTCH] */
  6338.   
  6339.   #else    /* V7/BSD TTY DRIVER */
  6340.   
  6341. ***************
  6342. *** 108,114 ****
  6343.   static struct     ltchars spec_chars;
  6344.   #define SuspC    spec_chars.t_suspc
  6345.   #else
  6346. ! #define    SuspC    CTRL('Z')
  6347.   #endif
  6348.   
  6349.   #endif
  6350. --- 114,120 ----
  6351.   static struct     ltchars spec_chars;
  6352.   #define SuspC    spec_chars.t_suspc
  6353.   #else
  6354. ! #define    SuspC    CONTROL_('Z')
  6355.   #endif
  6356.   
  6357.   #endif
  6358. ***************
  6359. *** 192,202 ****
  6360.       
  6361.   #ifdef RESIZING
  6362.   
  6363. ! sig_type winch()
  6364.   {
  6365.       struct winsize winsize;
  6366.   
  6367. !     (void) signal(SIGWINCH, winch);
  6368.       if (ioctl(0, TIOCGWINSZ, &winsize) >= 0
  6369.       && (winsize.ws_row != Lines || winsize.ws_col != Columns)) { 
  6370.       Lines = winsize.ws_row;
  6371. --- 198,208 ----
  6372.       
  6373.   #ifdef RESIZING
  6374.   
  6375. ! sig_type catch_winch()
  6376.   {
  6377.       struct winsize winsize;
  6378.   
  6379. !     (void) signal(SIGWINCH, catch_winch);
  6380.       if (ioctl(0, TIOCGWINSZ, &winsize) >= 0
  6381.       && (winsize.ws_row != Lines || winsize.ws_col != Columns)) { 
  6382.       Lines = winsize.ws_row;
  6383. ***************
  6384. *** 241,247 ****
  6385.       Lines = lines;
  6386.       cookie_size = magic_cookie_glitch;
  6387.       WRAP = auto_right_margin;
  6388. !     if (HAS_CAP(flash_screen)) strcpy(bell, flash_screen);
  6389.       if (! HAS_CAP(cursor_home))
  6390.       cursor_home = copy_str(tgoto(cursor_address, 0, 0));
  6391.   #else
  6392. --- 247,256 ----
  6393.       Lines = lines;
  6394.       cookie_size = magic_cookie_glitch;
  6395.       WRAP = auto_right_margin;
  6396. !     if (use_visible_bell && HAS_CAP(flash_screen)) 
  6397. !     strcpy(bell_str, flash_screen);
  6398. !     else if (HAS_CAP(bell)) 
  6399. !     strcpy(bell_str, bell);
  6400.       if (! HAS_CAP(cursor_home))
  6401.       cursor_home = copy_str(tgoto(cursor_address, 0, 0));
  6402.   #else
  6403. ***************
  6404. *** 270,276 ****
  6405.           && winsize.ws_row != 0 && winsize.ws_col != 0) { 
  6406.           Lines = winsize.ws_row;
  6407.           Columns = winsize.ws_col;
  6408. !         (void) signal(SIGWINCH, winch);
  6409.   #ifdef SV_INTERRUPT
  6410.           siginterrupt(SIGWINCH, 1);    /* make read from tty interruptable */
  6411.   #endif /* SV_INTERRUPT */
  6412. --- 279,285 ----
  6413.           && winsize.ws_row != 0 && winsize.ws_col != 0) { 
  6414.           Lines = winsize.ws_row;
  6415.           Columns = winsize.ws_col;
  6416. !         (void) signal(SIGWINCH, catch_winch);
  6417.   #ifdef SV_INTERRUPT
  6418.           siginterrupt(SIGWINCH, 1);    /* make read from tty interruptable */
  6419.   #endif /* SV_INTERRUPT */
  6420. ***************
  6421. *** 299,306 ****
  6422.       
  6423.       WRAP = tgetflag("am");
  6424.       
  6425. !     if (!opt_cap("vb", bell) && !opt_cap("bl", bell)) 
  6426. !     strcpy(bell, "\007");
  6427.       
  6428.   #endif /* !USE_TERMINFO */
  6429.       
  6430. --- 308,319 ----
  6431.       
  6432.       WRAP = tgetflag("am");
  6433.       
  6434. !     opt_cap("ti", enter_ca_mode);
  6435. !     opt_cap("te", exit_ca_mode);
  6436. !     if (!use_visible_bell || !opt_cap("vb", bell_str))
  6437. !     if (!opt_cap("bl", bell_str)) 
  6438. !         strcpy(bell_str, "\007");
  6439.       
  6440.   #endif /* !USE_TERMINFO */
  6441.       
  6442. ***************
  6443. *** 323,329 ****
  6444.       /* read a maximum of 10 characters in one burst; timeout in 1-200 ms */
  6445.       raw_tty.c_cc[VEOF] = KEY_BURST;
  6446.       raw_tty.c_cc[VEOL] = ((raw_tty.c_cflag & CBAUD) > B1200) ? 1 : 2;
  6447. !     
  6448.   #else    
  6449.       ioctl(0, TIOCGETC, &norm_chars);
  6450.       
  6451. --- 336,342 ----
  6452.       /* read a maximum of 10 characters in one burst; timeout in 1-200 ms */
  6453.       raw_tty.c_cc[VEOF] = KEY_BURST;
  6454.       raw_tty.c_cc[VEOL] = ((raw_tty.c_cflag & CBAUD) > B1200) ? 1 : 2;
  6455. !     set_term_speed((unsigned)(raw_tty.c_cflag & CBAUD));
  6456.   #else    
  6457.       ioctl(0, TIOCGETC, &norm_chars);
  6458.       
  6459. ***************
  6460. *** 332,341 ****
  6461.   #endif
  6462.       
  6463.       ospeed = norm_tty.sg_ospeed;
  6464. !     if (ospeed < B2400) slow_mode++;
  6465.       
  6466.       raw_tty.sg_flags |= RAW;
  6467. !     raw_tty.sg_flags &= ~(ECHO|CRMOD);
  6468.   
  6469.   #ifdef SV_INTERRUPT
  6470.       siginterrupt(SIGALRM, 1);        /* make read from tty interruptable */
  6471. --- 345,361 ----
  6472.   #endif
  6473.       
  6474.       ospeed = norm_tty.sg_ospeed;
  6475. !     set_term_speed((unsigned)ospeed);
  6476.       
  6477. +     raw_tty.sg_flags &= ~ECHO;
  6478. + #ifdef CBREAK
  6479. + #ifdef SV_INTERRUPT            /* make read from tty interruptable */
  6480. +     siginterrupt(SIGTSTP, 1);        /* this is necessary to redraw screen */
  6481. + #endif
  6482. +     raw_tty.sg_flags |= CBREAK;
  6483. + #else
  6484.       raw_tty.sg_flags |= RAW;
  6485. ! #endif
  6486.   
  6487.   #ifdef SV_INTERRUPT
  6488.       siginterrupt(SIGALRM, 1);        /* make read from tty interruptable */
  6489. ***************
  6490. *** 349,354 ****
  6491. --- 369,413 ----
  6492.       
  6493.       erase_key = EraseC;
  6494.       kill_key  = KillC;
  6495. +     visual_on();
  6496. + }
  6497. + static unsigned sp_table[] = {
  6498. +     B9600, 960,
  6499. + #ifdef B19200
  6500. +     B19200, 1920,
  6501. + #else
  6502. + #ifdef EXTA
  6503. +     EXTA, 1920,
  6504. + #endif
  6505. + #endif
  6506. + #ifdef B38400
  6507. +     B38400, 3840,
  6508. + #else
  6509. + #ifdef EXTB
  6510. +     EXTB, 3840,
  6511. + #endif
  6512. + #endif
  6513. +     B1200, 120,
  6514. +     B2400, 240,
  6515. +     B4800, 480,
  6516. +     B300,   30,
  6517. +     0,    0
  6518. + };
  6519. + static set_term_speed(sp)
  6520. + register unsigned long sp;
  6521. + {
  6522. +     register unsigned *tp;
  6523. +     for (tp = sp_table; *tp; tp += 2)
  6524. +     if (*tp == sp) {
  6525. +         terminal_speed = tp[1];
  6526. +         return;
  6527. +     }
  6528. +     
  6529. +     terminal_speed = 30;
  6530.   }
  6531.   
  6532.   home()
  6533. ***************
  6534. *** 356,363 ****
  6535. --- 415,437 ----
  6536.       putp(cursor_home);
  6537.   }
  6538.   
  6539. + static int curxy_c = -1, curxy_l, savxy_c = -1, savxy_l;
  6540. + save_xy()
  6541. + {
  6542. +     savxy_c = curxy_c; savxy_l = curxy_l;
  6543. + }
  6544. + restore_xy()
  6545. + {
  6546. +     if (savxy_c < 0) return;
  6547. +     gotoxy(savxy_c, savxy_l); fl;
  6548. + }
  6549.   gotoxy(c, l)
  6550. + int c, l;
  6551.   {
  6552. +     curxy_c = c; curxy_l = l;
  6553.       putp(tgoto(cursor_address, c, l));
  6554.   }
  6555.   
  6556. ***************
  6557. *** 368,373 ****
  6558. --- 442,448 ----
  6559.   #else
  6560.       tputs(clear_screen, Lines, outc);
  6561.   #endif
  6562. +     curxy_c = savxy_c = -1;
  6563.   }
  6564.   
  6565.   clrline()
  6566. ***************
  6567. *** 523,531 ****
  6568. --- 598,623 ----
  6569.       return 1;
  6570.   }
  6571.   
  6572. + static int is_visual = 0;
  6573. + visual_on()
  6574. + {
  6575. +     if (HAS_CAP(enter_ca_mode)) {
  6576. +     putp(enter_ca_mode);
  6577. +     is_visual = 1;
  6578. +     }
  6579. + }
  6580. + visual_off()
  6581. + {
  6582. +     if (is_visual && HAS_CAP(exit_ca_mode)) putp(exit_ca_mode), fl;
  6583. +     is_visual = 0;
  6584. + }
  6585. +   
  6586.   static int is_raw = 0;
  6587.   static int must_set_raw = 1;
  6588.   
  6589. + #ifndef CBREAK
  6590.   raw()
  6591.   {
  6592.       if (!flow_control) {
  6593. ***************
  6594. *** 572,577 ****
  6595. --- 664,693 ----
  6596.       return was_raw;
  6597.   }
  6598.   
  6599. + #else /* not CBREAK */
  6600. + raw()
  6601. + {
  6602. +     if (is_raw == 1)
  6603. +     return;
  6604. +     is_raw = 1;
  6605. +     ioctl(0, TIOCSETP, &raw_tty);    /* no TERMIO ??? */
  6606. + }
  6607. + no_raw()
  6608. + {
  6609. +     return 0;
  6610. + }
  6611. + unset_raw()
  6612. + {
  6613. +     if (is_raw == 0)
  6614. +     return 0;
  6615. +     ioctl(0, TIOCSETP, &norm_tty);    /* no TERMIO ??? */
  6616. +     is_raw = 0;
  6617. +     return 1;
  6618. + }
  6619. + #endif /* CBREAK */
  6620.   flush_input()
  6621.   {
  6622.   #ifdef HAVE_TERMIO
  6623. ***************
  6624. *** 651,657 ****
  6625.       c &= 0177;    /* done by ISTRIP on USG systems */
  6626.   #endif
  6627.       
  6628. !     if (c == CTRL('Q') || c == CTRL('S'))
  6629.           continue;
  6630.       
  6631.       any_multi = 0;
  6632. --- 767,773 ----
  6633.       c &= 0177;    /* done by ISTRIP on USG systems */
  6634.   #endif
  6635.       
  6636. !     if (c == CONTROL_('Q') || c == CONTROL_('S'))
  6637.           continue;
  6638.       
  6639.       any_multi = 0;
  6640. ***************
  6641. *** 687,692 ****
  6642. --- 803,815 ----
  6643.       goto next_key;
  6644.       }
  6645.   
  6646. + #ifdef CBREAK
  6647. +     if (s_redraw) {
  6648. +     s_redraw = 0;
  6649. +     return GETC_COMMAND | K_REDRAW;
  6650. +     }
  6651. + #endif
  6652.   #ifndef KEY_BURST
  6653.       if (n < 0) {
  6654.       if (errno != EINTR) s_hangup++;
  6655. ***************
  6656. *** 717,722 ****
  6657. --- 840,846 ----
  6658.       
  6659.       c = global_key_map[c];
  6660.       
  6661. + #ifndef CBREAK
  6662.       if (c == SuspC) {
  6663.       if (!enable_stop) goto next_key;
  6664.       if (suspend_nn())
  6665. ***************
  6666. *** 726,732 ****
  6667.       }
  6668.   
  6669.       if (c == IntrC) c = K_interrupt;
  6670. !     
  6671.       return c;
  6672.   }
  6673.   
  6674. --- 850,856 ----
  6675.       }
  6676.   
  6677.       if (c == IntrC) c = K_interrupt;
  6678. ! #endif
  6679.       return c;
  6680.   }
  6681.   
  6682. ***************
  6683. *** 800,806 ****
  6684.       for(;;) {
  6685.       lastc = c;
  6686.       c = get_c();
  6687. !     if (c & (0200 | GETC_COMMAND)) continue;
  6688.   
  6689.        kill_prefill_hack:
  6690.   
  6691. --- 924,930 ----
  6692.       for(;;) {
  6693.       lastc = c;
  6694.       c = get_c();
  6695. !     if (c & GETC_COMMAND) continue;
  6696.   
  6697.        kill_prefill_hack:
  6698.   
  6699. ***************
  6700. *** 942,948 ****
  6701.           break;
  6702.       }
  6703.       
  6704. !     if (c < SP) continue;
  6705.       
  6706.       if (i == max) continue;
  6707.   
  6708. --- 1066,1072 ----
  6709.           break;
  6710.       }
  6711.       
  6712. !     if (!isascii(c) || !isprint(c)) continue;
  6713.       
  6714.       if (i == max) continue;
  6715.   
  6716. ***************
  6717. *** 1044,1050 ****
  6718.       }
  6719.   
  6720.       if (in_macro) {
  6721. !     if (c <= 0) m_break();
  6722.       do_macro_processing = 1;
  6723.       }
  6724.       
  6725. --- 1168,1174 ----
  6726.       }
  6727.   
  6728.       if (in_macro) {
  6729. !     if (c < 0) m_break();
  6730.       do_macro_processing = 1;
  6731.       }
  6732.       
  6733. ***************
  6734. *** 1054,1060 ****
  6735.   
  6736.   ding()
  6737.   {
  6738. !     putp(bell);
  6739.       fl;
  6740.   }
  6741.   
  6742. --- 1178,1184 ----
  6743.   
  6744.   ding()
  6745.   {
  6746. !     putp(bell_str);
  6747.       fl;
  6748.   }
  6749.   
  6750. ***************
  6751. *** 1235,1240 ****
  6752. --- 1359,1365 ----
  6753.       int stand_on;
  6754.       char *fmt;
  6755.       static char cur_p[FILENAME];
  6756. +     static char saved_p[FILENAME];
  6757.       va_list ap;
  6758.       
  6759.       va_start(ap);
  6760. ***************
  6761. *** 1252,1257 ****
  6762. --- 1377,1390 ----
  6763.       return;
  6764.       }
  6765.       
  6766. +     if (fmt == P_SAVE) {
  6767. +     strcpy(saved_p, cur_p);
  6768. +     return;
  6769. +     }
  6770. +     
  6771. +     if (fmt == P_RESTORE)
  6772. +     strcpy(cur_p, saved_p);
  6773. +     
  6774.       if (prompt_line >= 0)
  6775.       gotoxy(0, prompt_line);
  6776.   
  6777. ***************
  6778. *** 1260,1266 ****
  6779.       return;
  6780.       }
  6781.   
  6782. !     if (fmt != P_REDRAW) 
  6783.       vsprintf(cur_p, fmt, va_args2toN);
  6784.   
  6785.       putchar('\r');
  6786. --- 1393,1399 ----
  6787.       return;
  6788.       }
  6789.   
  6790. !     if (fmt != P_REDRAW && fmt != P_RESTORE) 
  6791.       vsprintf(cur_p, fmt, va_args2toN);
  6792.   
  6793.       putchar('\r');
  6794. ***************
  6795. *** 1314,1319 ****
  6796. --- 1447,1457 ----
  6797.       }
  6798.       
  6799.       clrline();
  6800. +     if (fmt == P_RESTORE) 
  6801. +     restore_xy();
  6802. +     else
  6803. +     curxy_c = -1;
  6804.   }
  6805.   
  6806.   
  6807. *** /usr/storm/nn6.3.4/term.h    Mon Jul 10 13:36:33 1989
  6808. --- term.h    Fri Sep  8 12:47:00 1989
  6809. ***************
  6810. *** 12,17 ****
  6811. --- 12,19 ----
  6812.   
  6813.   extern so_gotoxy(), so_printf(), so_end();
  6814.   
  6815. + extern no_raw(), raw(), unset_raw();
  6816.   extern int Lines, Columns;
  6817.   extern int cookie_size;
  6818.   extern int WRAP, STANDOUT;
  6819. ***************
  6820. *** 27,33 ****
  6821.   
  6822.   /* special keys returned by get_c() */
  6823.   
  6824. ! #define    K_interrupt    CTRL('G')
  6825.   
  6826.   #define    K_up_arrow    0x0081
  6827.   #define    K_down_arrow    0x0082
  6828. --- 29,35 ----
  6829.   
  6830.   /* special keys returned by get_c() */
  6831.   
  6832. ! #define    K_interrupt    CONTROL_('G')
  6833.   
  6834.   #define    K_up_arrow    0x0081
  6835.   #define    K_down_arrow    0x0082
  6836. ***************
  6837. *** 57,63 ****
  6838.   #define    P_MOVE        (char *)1
  6839.   #define P_REDRAW    (char *)5
  6840.   #define    P_VERSION    (char *)9
  6841.   
  6842.   extern display_file();
  6843.   
  6844. --- 59,66 ----
  6845.   #define    P_MOVE        (char *)1
  6846.   #define P_REDRAW    (char *)5
  6847.   #define    P_VERSION    (char *)9
  6848. ! #define P_SAVE        (char *)13
  6849. ! #define P_RESTORE    (char *)17
  6850.   
  6851.   extern display_file();
  6852.   
  6853. *** /usr/storm/nn6.3.4/variable.c    Mon Jul 10 13:36:34 1989
  6854. --- variable.c    Fri Sep  8 12:47:00 1989
  6855. ***************
  6856. *** 7,12 ****
  6857. --- 7,13 ----
  6858.   import in_init;
  6859.   
  6860.   import char            /* string variables */
  6861. +     *decode_header_file,
  6862.       *default_distribution,
  6863.       *default_save_file,
  6864.       *extra_mail_headers,
  6865. ***************
  6866. *** 20,30 ****
  6867.       *pager,
  6868.       *patch_cmd,
  6869.       printer[],
  6870. !     *save_counter_format;
  6871.   
  6872.   import int            /* boolean variables */
  6873.       also_cross_postings,
  6874.       conf_append,
  6875.       conf_dont_sleep,
  6876.       delay_redraw,
  6877.       do_kill_handling,
  6878. --- 21,35 ----
  6879.       *pager,
  6880.       *patch_cmd,
  6881.       printer[],
  6882. !     *save_counter_format,
  6883. !     *unshar_header_file;
  6884.   
  6885.   import int            /* boolean variables */
  6886.       also_cross_postings,
  6887. +     also_subgroups,
  6888. +     compress_mode,
  6889.       conf_append,
  6890. +     conf_auto_quit,
  6891.       conf_dont_sleep,
  6892.       delay_redraw,
  6893.       do_kill_handling,
  6894. ***************
  6895. *** 43,64 ****
  6896.       novice,
  6897.       quick_save,
  6898.       save_report,
  6899.       show_article_date,
  6900.       show_current_time,
  6901.       silent,
  6902.       use_mail_folders,
  6903. !     use_newsrc;
  6904.   
  6905.   import int            /* integer variables */
  6906.       also_read_articles,
  6907.       article_limit,
  6908.       Debug,
  6909.       first_page_lines,
  6910.       fmt_linenum,
  6911.       Lines,
  6912.       overlap,
  6913.       preview_window,
  6914. !     retry_on_error;
  6915.   
  6916.   import char            /* key strokes */
  6917.       comp1_key,
  6918. --- 48,79 ----
  6919.       novice,
  6920.       quick_save,
  6921.       save_report,
  6922. +     seq_cross_filtering,
  6923.       show_article_date,
  6924.       show_current_time,
  6925.       silent,
  6926. +     slow_mode,
  6927.       use_mail_folders,
  6928. !     use_mmdf_folders,
  6929. !     use_newsrc,
  6930. !     use_visible_bell;
  6931.   
  6932.   import int            /* integer variables */
  6933.       also_read_articles,
  6934.       article_limit,
  6935. +     collapse_subject,
  6936. +     Columns,
  6937.       Debug,
  6938.       first_page_lines,
  6939.       fmt_linenum,
  6940.       Lines,
  6941. +     min_pv_window,
  6942.       overlap,
  6943.       preview_window,
  6944. !     re_layout,
  6945. !     retry_on_error,
  6946. !     slow_speed,
  6947. !     wrap_headers;
  6948.   
  6949.   import char            /* key strokes */
  6950.       comp1_key,
  6951. ***************
  6952. *** 80,95 ****
  6953.       char var_op;
  6954.       char **var_addr;
  6955.   } variables[] = {
  6956.       "backup",        V_BOOLEAN,    3,    (char **)&keep_rc_backup,
  6957.       "comp1_key",    V_KEY,        0,    (char **)&comp1_key,
  6958.       "comp2_key",    V_KEY,        0,    (char **)&comp2_key,
  6959. !     "confirm",        V_BOOLEAN,    0,    (char **)&conf_dont_sleep,
  6960.       "confirm-append",    V_BOOLEAN,    0,    (char **)&conf_append,
  6961.       "cross-post",    V_BOOLEAN,    0,    (char **)&also_cross_postings,
  6962.       "date",        V_BOOLEAN,    0,    (char **)&show_article_date,
  6963.       "debug",        V_INTEGER,    0,    (char **)&Debug,
  6964.       "default-distribution",V_STRING,    0,    (char **)&default_distribution,
  6965. !     "default-save-file",V_STRING,    0,    (char **)&default_save_file,
  6966.       "delay-redraw",    V_BOOLEAN,    0,    (char **)&delay_redraw,
  6967.       "erase-key",    V_KEY,        0,    (char **)&erase_key,
  6968.       "expert",        V_BOOLEAN,    4,    (char **)&novice,
  6969. --- 95,117 ----
  6970.       char var_op;
  6971.       char **var_addr;
  6972.   } variables[] = {
  6973. +     "also-subgroups",    V_BOOLEAN,    3,    (char **)&also_subgroups,
  6974.       "backup",        V_BOOLEAN,    3,    (char **)&keep_rc_backup,
  6975. +     "collapse-subject",    V_INTEGER,    3,    (char **)&collapse_subject,
  6976. +     "columns",        V_INTEGER,    1,    (char **)&Columns,
  6977.       "comp1_key",    V_KEY,        0,    (char **)&comp1_key,
  6978.       "comp2_key",    V_KEY,        0,    (char **)&comp2_key,
  6979. !     "compress",        V_BOOLEAN,    0,    (char **)&compress_mode,
  6980.       "confirm-append",    V_BOOLEAN,    0,    (char **)&conf_append,
  6981. +     "confirm-auto-quit",V_BOOLEAN,    0,    (char **)&conf_auto_quit,
  6982. +     "confirm-messages",    V_BOOLEAN,    0,    (char **)&conf_dont_sleep,
  6983. +     "cross-filter-seq",    V_BOOLEAN,    0,    (char **)&seq_cross_filtering,
  6984.       "cross-post",    V_BOOLEAN,    0,    (char **)&also_cross_postings,
  6985.       "date",        V_BOOLEAN,    0,    (char **)&show_article_date,
  6986.       "debug",        V_INTEGER,    0,    (char **)&Debug,
  6987. +     "decode-header-file",V_STRING,    0,    (char **)&decode_header_file,
  6988.       "default-distribution",V_STRING,    0,    (char **)&default_distribution,
  6989. !     "default-save-file",V_STRING,    3,    (char **)&default_save_file,
  6990.       "delay-redraw",    V_BOOLEAN,    0,    (char **)&delay_redraw,
  6991.       "erase-key",    V_KEY,        0,    (char **)&erase_key,
  6992.       "expert",        V_BOOLEAN,    4,    (char **)&novice,
  6993. ***************
  6994. *** 103,109 ****
  6995.       "kill",        V_BOOLEAN,    0,    (char **)&do_kill_handling,
  6996.       "kill-key",        V_KEY,        0,    (char **)&kill_key,
  6997.       "layout",        V_INTEGER,    1,    (char **)&fmt_linenum,
  6998. !     "limit",        V_INTEGER,    0,    (char **)&article_limit,
  6999.       "lines",        V_INTEGER,    1,    (char **)&Lines,
  7000.       "long-menu",    V_BOOLEAN,    1,    (char **)&long_menu,
  7001.       "macro-debug",    V_BOOLEAN,    0,    (char **)¯o_debug,
  7002. --- 125,131 ----
  7003.       "kill",        V_BOOLEAN,    0,    (char **)&do_kill_handling,
  7004.       "kill-key",        V_KEY,        0,    (char **)&kill_key,
  7005.       "layout",        V_INTEGER,    1,    (char **)&fmt_linenum,
  7006. !     "limit",        V_INTEGER,    2,    (char **)&article_limit,
  7007.       "lines",        V_INTEGER,    1,    (char **)&Lines,
  7008.       "long-menu",    V_BOOLEAN,    1,    (char **)&long_menu,
  7009.       "macro-debug",    V_BOOLEAN,    0,    (char **)¯o_debug,
  7010. ***************
  7011. *** 112,117 ****
  7012. --- 134,141 ----
  7013.       "mail-header",    V_STRING,    0,    (char **)&extra_mail_headers,
  7014.       "mail-record",    V_STRING,    2,    (char **)&mail_record,
  7015.       "mark-overlap",    V_BOOLEAN,    0,    (char **)&mark_overlap,
  7016. +     "min-window",    V_INTEGER,    1,    (char **)&min_pv_window,
  7017. +     "mmdf-format",    V_BOOLEAN,    0,    (char **)&use_mmdf_folders,
  7018.       "monitor",        V_BOOLEAN,    0,    (char **)&monitor_mode,
  7019.       "news-header",    V_STRING,    0,    (char **)&extra_news_headers,
  7020.       "news-record",    V_STRING,    2,    (char **)&news_record,
  7021. ***************
  7022. *** 119,140 ****
  7023.       "nn-re-style",    V_BOOLEAN,    0,    (char **)&nn_re_style,
  7024.       "old",        V_SPECIAL,    2,    (char **)NULL,
  7025.       "overlap",        V_INTEGER,    0,    (char **)&overlap,
  7026. !     "pager",        V_STRING,    0,    (char **)&pager,
  7027. !     "patch-cmd",    V_STRING,    0,    (char **)&patch_cmd,
  7028.       "printer",        V_STRING,    1,    (char **)printer,
  7029.       "quick-save",    V_BOOLEAN,    0,    (char **)&quick_save,
  7030.       "record",        V_SPECIAL,    1,    (char **)NULL,
  7031.       "repeat",        V_BOOLEAN,    0,    (char **)&fmt_rptsubj,
  7032.       "retry-on-error",    V_INTEGER,    0,    (char **)&retry_on_error,
  7033. !     "save-counter",    V_STRING,    0,    (char **)&save_counter_format,
  7034.       "save-report",    V_BOOLEAN,    0,    (char **)&save_report,
  7035.       "silent",        V_BOOLEAN,    0,    (char **)&silent,
  7036.       "sort",        V_BOOLEAN,    2,    (char **)&dont_sort_articles,
  7037.       "split",        V_BOOLEAN,    4,    (char **)&dont_split_digests,
  7038.       "stop",        V_INTEGER,    0,    (char **)&first_page_lines,
  7039.       "time",        V_BOOLEAN,    0,    (char **)&show_current_time,
  7040.       "window",        V_INTEGER,    1,    (char **)&preview_window,
  7041. !     "word-key",        V_KEY,        0,    (char **)&delword_key
  7042.   };
  7043.   
  7044.   #define TABLE_SIZE    (sizeof(variables)/sizeof(struct variable_defs))
  7045. --- 143,170 ----
  7046.       "nn-re-style",    V_BOOLEAN,    0,    (char **)&nn_re_style,
  7047.       "old",        V_SPECIAL,    2,    (char **)NULL,
  7048.       "overlap",        V_INTEGER,    0,    (char **)&overlap,
  7049. !     "pager",        V_STRING,    3,    (char **)&pager,
  7050. !     "patch-cmd",    V_STRING,    3,    (char **)&patch_cmd,
  7051.       "printer",        V_STRING,    1,    (char **)printer,
  7052.       "quick-save",    V_BOOLEAN,    0,    (char **)&quick_save,
  7053. +     "re-layout",    V_INTEGER,    0,    (char **)&re_layout,
  7054.       "record",        V_SPECIAL,    1,    (char **)NULL,
  7055.       "repeat",        V_BOOLEAN,    0,    (char **)&fmt_rptsubj,
  7056.       "retry-on-error",    V_INTEGER,    0,    (char **)&retry_on_error,
  7057. !     "save-counter",    V_STRING,    3,    (char **)&save_counter_format,
  7058.       "save-report",    V_BOOLEAN,    0,    (char **)&save_report,
  7059.       "silent",        V_BOOLEAN,    0,    (char **)&silent,
  7060. +     "slow-mode",    V_BOOLEAN,    0,    (char **)&slow_mode,
  7061. +     "slow-speed",    V_INTEGER,    0,    (char **)&slow_speed,
  7062.       "sort",        V_BOOLEAN,    2,    (char **)&dont_sort_articles,
  7063.       "split",        V_BOOLEAN,    4,    (char **)&dont_split_digests,
  7064.       "stop",        V_INTEGER,    0,    (char **)&first_page_lines,
  7065.       "time",        V_BOOLEAN,    0,    (char **)&show_current_time,
  7066. +     "unshar-header-file",V_STRING,    0,    (char **)&unshar_header_file,
  7067. +     "visible-bell",     V_BOOLEAN,    0,    (char **)&use_visible_bell,
  7068.       "window",        V_INTEGER,    1,    (char **)&preview_window,
  7069. !     "word-key",        V_KEY,        0,    (char **)&delword_key,
  7070. !     "wrap-header-margin",V_INTEGER,    2,    (char **)&wrap_headers
  7071.   };
  7072.   
  7073.   #define TABLE_SIZE    (sizeof(variables)/sizeof(struct variable_defs))
  7074. ***************
  7075. *** 143,149 ****
  7076.   #define BOOL_VAR    (*((int *)(var->var_addr)))
  7077.   #define STR_VAR        (*(var->var_addr))
  7078.   #define CBUF_VAR    ((char *)(var->var_addr))
  7079. ! #define KEY_VAR        (*((char *)(var->var_addr)))
  7080.   
  7081.   
  7082.   static struct variable_defs *lookup_variable(variable)
  7083. --- 173,179 ----
  7084.   #define BOOL_VAR    (*((int *)(var->var_addr)))
  7085.   #define STR_VAR        (*(var->var_addr))
  7086.   #define CBUF_VAR    ((char *)(var->var_addr))
  7087. ! #define KEY_VAR        (*((unsigned char *)(var->var_addr)))
  7088.   
  7089.   
  7090.   static struct variable_defs *lookup_variable(variable)
  7091. ***************
  7092. *** 199,214 ****
  7093.   
  7094.       switch (var->var_op) {
  7095.        case 0:
  7096. !         if (val_string) STR_VAR = copy_str(val_string);
  7097.           break;
  7098.   
  7099.        case 1:
  7100. !         if (val_string) strcpy(CBUF_VAR, val_string);
  7101.           break;
  7102.   
  7103.        case 2:
  7104. !         adjust(val_string);
  7105. !         if (val_string) STR_VAR = home_relative(val_string);
  7106.           break;
  7107.       }
  7108.       break;
  7109. --- 229,255 ----
  7110.   
  7111.       switch (var->var_op) {
  7112.        case 0:
  7113. !         STR_VAR = (on && val_string) ? copy_str(val_string) : (char *)NULL;
  7114.           break;
  7115.   
  7116.        case 1:
  7117. !         strcpy(CBUF_VAR, (on && val_string) ? val_string : "");
  7118.           break;
  7119.   
  7120.        case 2:
  7121. !         if (on) {
  7122. !         adjust(val_string);
  7123. !         if (val_string) STR_VAR = home_relative(val_string);
  7124. !         } else
  7125. !         STR_VAR = (char *)NULL;
  7126. !         break;
  7127. !      case 3:
  7128. !         if (!on || val_string == NULL) {
  7129. !         msg("Cannot unset string `%s'", variable);
  7130. !         break;
  7131. !         }
  7132. !         STR_VAR = copy_str(val_string);
  7133.           break;
  7134.       }
  7135.       break;
  7136. ***************
  7137. *** 255,268 ****
  7138.   
  7139.       switch (var->var_op) {
  7140.        case 0:
  7141.           INT_VAR = value;        
  7142.           break;
  7143. !         
  7144. !      case 1:
  7145. !         INT_VAR = value; 
  7146. !         return 1;
  7147.       }
  7148. !     break;
  7149.       
  7150.        case V_KEY:
  7151.       switch (var->var_op) {
  7152. --- 296,312 ----
  7153.   
  7154.       switch (var->var_op) {
  7155.        case 0:
  7156. +      case 1:
  7157.           INT_VAR = value;        
  7158.           break;
  7159. !      case 2:
  7160. !      case 3:
  7161. !         if (!on) value = -1;
  7162. !         INT_VAR = value;        
  7163. !         break;
  7164.       }
  7165. !     return (var->var_op & 1);
  7166.       
  7167.        case V_KEY:
  7168.       switch (var->var_op) {
  7169. ***************
  7170. *** 288,294 ****
  7171.           
  7172.        case 2:
  7173.           also_read_articles = on;
  7174. !         article_limit = value;
  7175.           break;
  7176.       }        
  7177.       break;
  7178. --- 332,338 ----
  7179.           
  7180.        case 2:
  7181.           also_read_articles = on;
  7182. !         article_limit = (on && value > 0) ? value : -1;
  7183.           break;
  7184.       }        
  7185.       break;
  7186.